批量任务处理:当需要并发执行多个任务,然后等待所有任务执行完毕后进行下一步操作时,可以使用这两种方法来等待所有任务执行完毕。
线程池管理:在使用线程池执行任务时,有时需要等待所有任务执行完毕后再关闭线程池,可以使用这两种方法来实现这一需求。
并发测试:在并发测试中,有时需要等待所有测试线程执行完毕后再进行结果汇总和分析,这时可以使用这两种方法来等待所有测试线程执行完毕。
总之,无论是在需要等待多个任务执行完毕后再进行下一步操作的业务场景,还是在线程池管理或并发测试等技术领域,这两种方法都可以非常有用。它们能够帮助实现多线程任务的协同和管理,确保所有任务都执行完毕后再进行后续操作。
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.CountDownLatch;
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CountDownLatch latch = new CountDownLatch(threadCount);
List<Integer> list=new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
int finalI = i;
executor.submit(() -> {
// 执行线程任务
try {
System.out.println(finalI);
int i1 = get();
System.out.println("===============================");
list.add(i1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 任务执行完毕后,调用countDown()
latch.countDown();
});
}
// 等待所有线程执行完毕
latch.await();
// 关闭线程池
executor.shutdown();
System.out.println("******************************");
System.out.println(list);
}
public static int get() throws InterruptedException {
Thread.sleep(3000);
return new Random().nextInt(30);
}
}
CountDownLatch
来等待所有线程执行完毕。countDown()
方法来减少计数器的值,当计数器的值为0时,await()
方法就会返回,表示所有线程执行完毕。shutdown()
方法来关闭线程池。import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.Random;
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
List<Integer> list=new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
int finalI = i;
executor.submit(() -> {
// 执行线程任务
try {
System.out.println(finalI);
int i1 = get();
System.out.println("===============================");
list.add(i1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
// 关闭线程池
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); // 等待所有任务执行完毕
System.out.println("************************************");
System.out.println(list);
// 所有任务执行完毕后会继续执行这里的代码
}
public static int get() throws InterruptedException {
Thread.sleep(3000);
return new Random().nextInt(30);
}
}
executor.shutdown()
来关闭线程池。executor.awaitTermination()
来等待所有任务执行完毕。当所有任务执行完毕后,awaitTermination
会返回,然后可以继续执行后续的代码。在使用这两种方法等待线程执行完毕时,需要注意以下几点:
确保所有线程都能够正常执行完毕,否则可能会出现死锁等问题。
在使用
CountDownLatch
等待线程执行完毕时,需要在每个线程的任务执行完毕后调用countDown()
方法,否则计数器的值不会减少,就会一直等待下去。在使用
awaitTermination
等待线程执行完毕时,需要调用shutdown()
方法来关闭线程池,否则线程池会一直等待新的任务到来,无法退出。在使用
awaitTermination
等待线程执行完毕时,需要注意超时时间的设置,否则可能会一直等待下去。在使用多线程时,需要注意线程安全问题,避免出现竞态条件等问题。
总之,在使用这两种方法等待线程执行完毕时,需要仔细考虑业务逻辑和线程安全问题,确保程序能够正确地执行。