这里是关于“Java并发编程示例(六):等待线程执行终止”的完整攻略。
标题
Java并发编程示例(六):等待线程执行终止
简介
在Java并发编程中,常常需要等待一个线程或多个线程的执行终止,才能接着执行下一步的操作。这篇文章将介绍如何等待线程执行终止的几种方法,以及使用这些方法的示例。
阻塞等待线程执行终止的方法
- 使用Thread.join()方法
在主线程中调用Thread.join()方法,可以等待另一个线程执行完毕后再执行主线程。示例代码如下:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// do something
}
});
t.start();
t.join(); // 阻塞当前线程,等待t线程执行完毕
// do something after t thread completes
- 使用CountDownLatch
CountDownLatch是Java提供的一个同步工具类。通过它,可以设置一个计数器,当计数器变为0时,主线程才能继续执行。示例代码如下:
CountDownLatch latch = new CountDownLatch(1);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// do something
latch.countDown(); // 计数器减1
}
});
t.start();
latch.await(); // 阻塞当前线程,等待计数器变为0
// do something after t thread completes
- 使用CyclicBarrier
CyclicBarrier也是Java提供的一个同步工具类。它可以等待一组线程全部执行完毕后再执行主线程。示例代码如下:
CyclicBarrier barrier = new CyclicBarrier(2); // 2表示有2个线程需要等待
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// do something
try {
barrier.await(); // 等待其他线程执行完毕
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
});
t.start();
barrier.await(); // 阻塞当前线程,等待t线程执行完毕
// do something after t thread completes
案例说明
- 使用Thread.join()方法
使用Thread.join()方法可以实现一个简单的多线程下载器。下载器启动多个线程同时下载文件,主线程等待所有线程下载完毕后再合并文件。
代码示例:
public class MultiThreadDownloader {
private static final String FILE_URL = "http://example.com/bigfile.zip";
private static final String FILE_PATH = "bigfile.zip";
private int threadCount;
private volatile int finishedThreadCount;
public MultiThreadDownloader(int threadCount) {
this.threadCount = threadCount;
}
public void download() throws IOException, InterruptedException {
URL url = new URL(FILE_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("HTTP response code is " + responseCode);
}
int fileLength = conn.getContentLength();
RandomAccessFile file = new RandomAccessFile(FILE_PATH, "rw");
file.setLength(fileLength);
int blockSize = fileLength / threadCount;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
long startPosition = i * blockSize;
long endPosition = (i == threadCount - 1) ? fileLength - 1 : startPosition + blockSize - 1;
new DownloadThread(startPosition, endPosition, i, latch).start();
}
latch.await();
file.close();
System.out.println("Download completed.");
}
private class DownloadThread extends Thread {
private long startPosition;
private long endPosition;
private int threadId;
private CountDownLatch latch;
public DownloadThread(long startPosition, long endPosition, int threadId, CountDownLatch latch) {
this.startPosition = startPosition;
this.endPosition = endPosition;
this.threadId = threadId;
this.latch = latch;
}
@Override
public void run() {
try {
URL url = new URL(FILE_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
int responseCode = conn.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_PARTIAL) {
throw new RuntimeException("HTTP response code is " + responseCode);
}
InputStream in = conn.getInputStream();
RandomAccessFile file = new RandomAccessFile(FILE_PATH, "rw");
file.seek(startPosition);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
file.write(buffer, 0, bytesRead);
}
in.close();
file.close();
finishedThreadCount++;
System.out.println("Thread " + threadId + " finished downloading.");
if (finishedThreadCount == threadCount) {
latch.countDown();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException, InterruptedException {
MultiThreadDownloader downloader = new MultiThreadDownloader(4);
downloader.download();
}
}
- 使用CyclicBarrier
使用CyclicBarrier可以实现一个简单的多线程排序器。排序器分配多个线程同时执行排序,主线程等待所有线程排序完毕后再合并结果。
代码示例:
public class MultiThreadSorter {
private int threadCount;
private int[] data;
private CyclicBarrier barrier;
public MultiThreadSorter(int threadCount, int[] data) {
this.threadCount = threadCount;
this.data = data;
this.barrier = new CyclicBarrier(threadCount, new Runnable() {
@Override
public void run() {
mergeSort();
}
});
}
public void sort() {
int blockSize = data.length / threadCount;
for (int i = 0; i < threadCount; i++) {
int start = i * blockSize;
int end = (i == threadCount - 1) ? data.length - 1 : start + blockSize - 1;
new SortThread(start, end, barrier).start();
}
}
private void mergeSort() {
int[] temp = new int[data.length];
mergeSort(data, temp, 0, data.length - 1);
}
private void mergeSort(int[] arr, int[] temp, int start, int end) {
if (start >= end) {
return;
}
int mid = start + (end - start) / 2;
mergeSort(arr, temp, start, mid);
mergeSort(arr, temp, mid + 1, end);
merge(arr, temp, start, mid, end);
}
private void merge(int[] arr, int[] temp, int start, int mid, int end) {
System.arraycopy(arr, start, temp, start, end - start + 1);
int i = start;
int j = mid + 1;
for (int k = start; k <= end; k++) {
if (i > mid) {
arr[k] = temp[j++];
} else if (j > end) {
arr[k] = temp[i++];
} else if (temp[i] < temp[j]) {
arr[k] = temp[i++];
} else {
arr[k] = temp[j++];
}
}
}
private class SortThread extends Thread {
private int start;
private int end;
private CyclicBarrier barrier;
public SortThread(int start, int end, CyclicBarrier barrier) {
this.start = start;
this.end = end;
this.barrier = barrier;
}
@Override
public void run() {
Arrays.sort(data, start, end + 1);
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int[] data = { 5, 9, 3, 7, 1, 8, 2, 6, 4 };
MultiThreadSorter sorter = new MultiThreadSorter(4, data);
sorter.sort();
System.out.println(Arrays.toString(data));
}
}
以上就是等待线程执行终止的几种方法及示例说明。希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程示例(六):等待线程执行终止 - Python技术站