## 1. 使用 `Thread.join()`标签:继续执行,Thread,主线,System,try,线程,println,out From: https://www.cnblogs.com/rebecca2020/p/18357801
`Thread.join()` 方法会让主线程等待被调用线程执行完毕之后再继续执行。
#### 示例代码:
```java
public class Main {
public static void main(String[] args) {
// 创建3个线程
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 is done");
});
Thread thread2 = new Thread(() -> {
System.out.println("Thread 2 is running");
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread 2 is done");
});
Thread thread3 = new Thread(() -> {
System.out.println("Thread 3 is running");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread 3 is done");
});
// 启动线程
thread1.start();
thread2.start();
thread3.start();
try {
// 主线程等待子线程执行完毕
thread1.join();
thread2.join();
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 主线程继续执行
System.out.println("All threads have finished. Main thread continues.");
}
}
```
#### 解释:
- `thread1.join()` 会让主线程等待 `thread1` 执行完毕后再继续往下执行。
- `thread2.join()` 和 `thread3.join()` 也类似。
- 当所有线程都执行完毕后,主线程会继续执行接下来的逻辑。
### 2. 使用 `ExecutorService` 和 `awaitTermination()`
`ExecutorService` 提供了管理线程池的能力,使用它可以方便地等待所有任务执行完毕。
#### 示例代码:
```java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交3个任务
executor.submit(() -> {
System.out.println("Task 1 is running");
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Task 1 is done");
});
executor.submit(() -> {
System.out.println("Task 2 is running");
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Task 2 is done");
});
executor.submit(() -> {
System.out.println("Task 3 is running");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Task 3 is done");
});
// 停止接收新的任务,并等待已提交任务执行完毕
executor.shutdown();
try {
// 等待所有任务完成,最多等待10分钟
if (!executor.awaitTermination(10, TimeUnit.MINUTES)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
// 主线程继续执行
System.out.println("All tasks have finished. Main thread continues.");
}
}
```
#### 解释:
- `executor.shutdown()` 会停止接收新的任务,但会让已经提交的任务继续执行。
- `executor.awaitTermination()` 会等待所有任务完成,等待的时间可以设置。如果超时或者被中断,可以调用 `shutdownNow()` 来强制终止所有线程。
### 3. 使用 `CountDownLatch`
`CountDownLatch` 是一个同步辅助类,用于在一个或多个线程完成一组操作之前,使一个或多个线程等待。
#### 示例代码:
```java
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
int numberOfThreads = 3;
CountDownLatch latch = new CountDownLatch(numberOfThreads);
// 创建并启动3个线程
new Thread(() -> {
System.out.println("Thread 1 is running");
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread 1 is done");
latch.countDown(); // 线程结束时,计数器减1
}).start();
new Thread(() -> {
System.out.println("Thread 2 is running");
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread 2 is done");
latch.countDown(); // 线程结束时,计数器减1
}).start();
new Thread(() -> {
System.out.println("Thread 3 is running");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("Thread 3 is done");
latch.countDown(); // 线程结束时,计数器减1
}).start();
try {
// 主线程等待,直到计数器变为0
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 主线程继续执行
System.out.println("All threads have finished. Main thread continues.");
}
}
```
#### 解释:
- 每个线程在执行完任务后调用 `latch.countDown()`,减少计数。
- 主线程调用 `latch.await()` 等待,直到计数器变为0,即所有线程都完成了任务。
### 总结
- **`Thread.join()`** 是最简单直接的方式,但需要手动管理每个线程。
- **`ExecutorService`** 提供了更强大的线程池管理和任务控制功能。
- **`CountDownLatch`** 非常适合需要在多个线程完成各自任务后,再让主线程继续的场景。
根据具体的应用场景和需求,选择最合适的方法来实现。