1

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.

GC001
  • 871
  • 8
  • 12
  • This sounds like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Can you explain your use case? – Turing85 Aug 01 '20 at 21:10
  • @Turing85, this is not an XY problem because I know the workaround(having separate thread pools) works. However, I am looking for a better solution. My use case is that I want a SINGLE thread pool for scheduling tasks and retries if failed, and my retry only retries part of my task. For example, I have 3 steps for a task. Step1 works, Step2 is retriable and it fails, but Step3 is not retriable. Let's say it runs on T1. When step2 fails, I want to schedule its retry in the same pool. If retry succeeds, T1 should resume from Step3. My question is to find a way that T1 can be realeased for retry. – GC001 Aug 01 '20 at 21:33
  • As far as I know, there is no possibility to "park" a task once it is executed by a thread. In essence, if you have an `ExecutorService` with exactly one thread, and the thread executes a task, the task will not released until the taks is completed or throws an exception. Thus, the `ExecutorService` and all scheduled tasks are stuck when the currently exeucted task is in a deadlock. You can park the thread through the mechanism of [`wait()`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Object.html#wait()), but this parks the thread, not the task. – Turing85 Aug 01 '20 at 21:45
  • "Theoretically, the process will be stuck when all tasks submitted failed immediately because there are no threads for running the retry tasks" - maybe, a watcher thread to abort the failed tasks after a timeout would work? – Andrew Vershinin Aug 01 '20 at 22:27
  • So it is a XY-Problem after all... Maybe. But for this to work, each task would have to periodcally check for abortion (the taks cannot be "killed" externally, but must be asked to abort). Another solution would be to split the execution of one task into multiple tasks. But none of those solutions will guarantee that the system will make progress. There is a reason why reactive programming forbids blocking operations on worker threads. – Turing85 Aug 01 '20 at 22:32
  • @AndrewVershinin, yeah, I believe there are different kinds of workaround to implement this. What I am interested in is whether JAVA provides such an inter-thread communication mechanism that "awaits and releases resource and will be notified later". – GC001 Aug 01 '20 at 23:51
  • @Turing85, same as above, what I want out of this post is whether JAVA provides such an inter-thread communication mechanism that "awaits and releases resource and will be notified later" – GC001 Aug 01 '20 at 23:53

1 Answers1

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. 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

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38