我正在寻找一个线程间的通信机制,可以等待和释放底层线程资源在同一时间。在下面的示例中,当仅用一个线程初始化executorService时,第二个任务将被卡住,因为线程被t1持有,即使它是await。下面的代码只有在您更改为用2个线程初始化executorService时才能工作。
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
CountDownLatch cdl = new CountDownLatch(1);
executorService.submit(() -> {
System.out.println("start t1");
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 done");
});
executorService.submit(() -> {
System.out.println("start t2");
cdl.countDown();
System.out.println("t2 done");
});
System.out.println("Master thread ends");
}用一个线程初始化executorService时的输出。
start t1
Master thread ends用两个线程初始化executorService时的输出。
start t1
Master thread ends
start t2
t2 done
t1 done理想情况下,当t1等待时,它不需要保存底层线程,这样task2就可以在这个线程池中运行。这个问题的一个真实的用例是,如果我有一个线程池,并且任务将被提交/调度回同一个池进行重试。理论上,当所有提交的任务都立即失败时,由于没有运行重试任务的线程,进程将被卡住。
为retry创建一个单独的线程池可以解决这个问题,但是我想知道JAVA是否提供了一种线程间通信机制,允许同时等待和释放底层线程,因此只需要一个线程池。
发布于 2020-08-02 15:19:35
释放底层线程资源的唯一方法是从任务的主要方法(通常是Runnable::run)完全返回。若要同时等待,应以异步方式订阅事件生成器。并不是每个生产者都有异步接口。CompletbleFuture有(whenComplete方法),但CountDownLatch没有。但是,您可以使用异步终结性扩展CountDownLatch,订阅它的完成,从run()返回和等待。我是在我的DF4J库中这样做的:AsyncCountDownLatch.java
https://stackoverflow.com/questions/63210084
复制相似问题