英文:
What's the inter-thread communication mechanism that can await and release underlying thread resource at the same time
问题
我正在寻找一种可以同时等待和释放底层线程资源的线程间通信机制。在我的下面的示例中,当executorService
只使用1个线程进行初始化时,第二个任务将会被阻塞,因为线程被t1占用,即使它在等待。只有当您将executorService
初始化为2个线程时,下面的代码才能正常工作。
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
初始化为1个线程时的输出。
start t1
Master thread ends
当executorService
初始化为2个线程时的输出。
start t1
Master thread ends
start t2
t2 done
t1 done
理想情况下,当t1等待时,它不需要持有底层线程,以便任务2可以在此线程池内运行。这个问题的一个现实用例是,如果我有一个线程池,并且任务将被提交/调度回同一个池进行重试。从理论上讲,当所有提交的任务立即失败时,由于没有线程来运行重试任务,该过程将会被阻塞。
创建一个单独的重试线程池可以解决这个问题,但我想知道JAVA是否提供了一种线程间通信机制,允许同时等待和释放底层线程,以便只需要一个线程池。
英文:
I am looking for an inter-thread communication mechanism that can await and release underlying thread resource at the same time. In my example below, when the executorService
is initialized with only 1 thread, the second task will be stuck because the thread is held by t1 even though it's await
. The code below will only work if you change to initialize the executorService
with 2 threads.
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");
}
The output when executorService
is initialized with 1 thread.
start t1
Master thread ends
The output when executorService
is initialized with 2 threads.
start t1
Master thread ends
start t2
t2 done
t1 done
Ideally, when t1 is waiting, it doesn't need to hold the underlying thread such that task2 can run within this thread pool. A real-world use case of this problem is that if I have a thread pool, and the tasks will be submitted/scheduled back to the same pool for retries. Theoretically, the process will be stuck when all tasks submitted failed immediately because there are no threads for running the retry tasks.
Creating a separate thread pool for retry can solve this problem, but I am wondering if JAVA provides an inter-thread communication mechanism that allows waiting and releasing the underlying thread at the same time, so that only 1 thread pool is needed.
答案1
得分: 0
The only way to release underlying thread resource is to completely return from the main method of the task (usually Runnable::run). To await at the same time, the event producer should be subscribed in asynchronous way. Not every producer has asynchronous interface. CompletableFuture has (method whenComplete), but CountDownLatch has not. However, you can extend CountDownLatch with asynchronous functionality, subscribe to its completion, return from run() and wait. I did so in my DF4J library: AsyncCountDownLatch.java
英文:
The only way to release underlying thread resource is to completely return from the main method of the task (usually Runnable::run). To await at the same time, the event producer should be subscribed in asynchronous way. Not every producer has asynchronous interface. CompletbleFuture has (method whenComplete), but CountDownLatch has not. However, you can extend CountDownLatch with asynchronous finctionality, subscribe to its completion, return from run() and wait. I did so in my DF4J library: AsyncCountDownLatch.java
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论