Thread 类的 join() 方法可以让主线程等待某个线程执行完毕
public class ThreadJoinExample {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {System.out.println("Thread 1 is running");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread 1 finished");});Thread thread2 = new Thread(() -> {System.out.println("Thread 2 is running");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread 2 finished");});thread1.start();thread2.start();// 主线程等待子线程thread1.join();thread2.join();System.out.println("All threads finished. Main thread continues.");}
}
CountDownLatch是一个线程同步工具类,可以让主线程等待多个线程完成任务
public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int threadCount = 2;CountDownLatch latch = new CountDownLatch(threadCount);Runnable task = () -> {System.out.println(Thread.currentThread().getName() + " is running");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " finished");latch.countDown(); // 计数器减1};Thread thread1 = new Thread(task, "Thread 1");Thread thread2 = new Thread(task, "Thread 2");thread1.start();thread2.start();latch.await(); // 主线程等待计数器归零System.out.println("All threads finished. Main thread continues.");}
}
使用ExecutorService可以方便地管理线程池,并通过invokeAll()等待所有线程完成
public class ExecutorServiceExample {public static void main(String[] args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(2);List<Callable<Void>> tasks = new ArrayList<>();tasks.add(() -> {System.out.println("Task 1 is running");Thread.sleep(1000);System.out.println("Task 1 finished");return null;});tasks.add(() -> {System.out.println("Task 2 is running");Thread.sleep(2000);System.out.println("Task 2 finished");return null;});executor.invokeAll(tasks); // 等待所有任务完成System.out.println("All tasks finished. Main thread continues.");executor.shutdown();}
}
如果任务可以分而治之,可以使用ForkJoinPool框架
public class ForkJoinPoolExample {static class SumTask extends RecursiveTask<Long> {private static final int THRESHOLD = 10; // 阈值,决定任务拆分的粒度private final int[] array;private final int start;private final int end;public SumTask(int[] array, int start, int end) {this.array = array;this.start = start;this.end = end;}@Overrideprotected Long compute() {if (end - start <= THRESHOLD) {// 任务足够小,直接计算long sum = 0;for (int i = start; i < end; i++) {sum += array[i];}return sum;} else {// 任务太大,分成两个子任务int mid = (start + end) / 2;SumTask leftTask = new SumTask(array, start, mid);SumTask rightTask = new SumTask(array, mid, end);// 递归执行子任务leftTask.fork(); // 异步执行long rightResult = rightTask.compute(); // 当前线程直接执行右任务long leftResult = leftTask.join(); // 等待左任务结果// 合并结果return leftResult + rightResult;}}}public static void main(String[] args) {// 创建一个大数组int[] array = new int[100];for (int i = 0; i < array.length; i++) {array[i] = i + 1;}// 创建 ForkJoinPoolForkJoinPool forkJoinPool = new ForkJoinPool(4);// 提交主任务SumTask task = new SumTask(array, 0, array.length);long result = forkJoinPool.invoke(task); // 阻塞等待结果System.out.println("Sum of array elements: " + result);// 关闭 ForkJoinPoolforkJoinPool.shutdown();}
}
ExecutorService的shutdown() + awaitTermination(),这种方法通过线程池的关闭操作配合awaitTermination()来等待线程池中的所有任务完成
public class ThreadPoolAwaitExample {public static void main(String[] args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(3);for (int i = 1; i <= 5; i++) {int taskId = i;executor.submit(() -> {System.out.println("Task " + taskId + " is running");try {Thread.sleep(1000); // 模拟任务耗时} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task " + taskId + " completed");});}executor.shutdown(); // 禁止提交新任务if (executor.awaitTermination(5, TimeUnit.SECONDS)) { // 等待所有任务完成,超时时间可调整System.out.println("All tasks completed. Main thread continues.");} else {System.out.println("Timeout reached before tasks completed.");}}
}
使用 CompletionService,CompletionService可以结合线程池使用,用于提交和获取任务的执行结果。通过轮询结果,确保所有任务完成
public class CompletionServiceExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(3);CompletionService<String> completionService = new ExecutorCompletionService<>(executor);for (int i = 1; i <= 5; i++) {int taskId = i;completionService.submit(() -> {Thread.sleep(1000);return "Task " + taskId + " result";});}for (int i = 1; i <= 5; i++) {Future<String> future = completionService.take(); // 阻塞直到有结果可获取System.out.println(future.get());}executor.shutdown();System.out.println("All tasks completed. Main thread continues.");}
}
通过 Future 的 get(),ExecutorService 的 submit() 方法返回一个 Future 对象,可以通过 Future.get() 阻塞等待任务完成。
public class FutureGetExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<String>> futures = new ArrayList<>();for (int i = 1; i <= 5; i++) {int taskId = i;futures.add(executor.submit(() -> {Thread.sleep(1000);return "Task " + taskId + " result";}));}for (Future<String> future : futures) {System.out.println(future.get()); // 阻塞等待任务完成}executor.shutdown();System.out.println("All tasks completed. Main thread continues.");}
}
invokeAll() 方法,ExecutorService 提供了 invokeAll() 方法,可以一次性提交一组任务,并阻塞直到所有任务完成。
public class InvokeAllExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(3);List<Callable<String>> tasks = new ArrayList<>();for (int i = 1; i <= 5; i++) {int taskId = i;tasks.add(() -> {Thread.sleep(1000);return "Task " + taskId + " result";});}List<Future<String>> futures = executor.invokeAll(tasks); // 阻塞等待所有任务完成for (Future<String> future : futures) {System.out.println(future.get());}executor.shutdown();System.out.println("All tasks completed. Main thread continues.");}
}
使用 CountDownLatch,通过线程池配合 CountDownLatch 实现主线程等待所有任务完成。
public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int taskCount = 5;CountDownLatch latch = new CountDownLatch(taskCount);ExecutorService executor = Executors.newFixedThreadPool(3);for (int i = 1; i <= taskCount; i++) {int taskId = i;executor.submit(() -> {try {System.out.println("Task " + taskId + " is running");Thread.sleep(1000); // 模拟任务耗时} catch (InterruptedException e) {e.printStackTrace();} finally {latch.countDown(); // 每完成一个任务,计数器减1}System.out.println("Task " + taskId + " completed");});}latch.await(); // 主线程等待计数器归零executor.shutdown();System.out.println("All tasks completed. Main thread continues.");}
}