简体   繁体   中英

Is it possible to wait the main thread while all the threads of executor service are processing tasks

I am having a scenario of around inserting millions of data into the back end and currently using executor framework to load this. I will explain my problem in simpler terms.

In the below case, I am having 10 runnable and three threads to execute the same. Consider my runnable is doing an insert operation and it is taking time to complete the task. When I checked,It is understood that,if all the threads are busy, the other tasks will go to the queue and once the threads completed the tasks,it will fetch the tasks from the pool and complete it.

So in this case, object of SampleRunnable 4 to 10 will be created and this will be in the pool.

Problem: Since I need to load millions of tasks,I cannot load all the records in queue which can lead to memory issues. So my question is instead of taking all tasks in the queue,is it possible to make the main thread waiting until any one of the executor worker threads becomes available.

Following approaches I tried as a work around instead of queuing this much tasks:

Approach 1: Used Array Blocking Queue for executor and gave the size as 5 (for eg) So in this case, when the 9th task comes,this will throw RejectedExecutionException and in the catch clause,put a sleep for 1 minute and recursively trying the same.This will get picked up on any of the retry when the thread is available.

Approach 2: Used shut down and await termination. ie if the task count is 5, i am putting shut down and await termination. In the await Termination 'if' block (executor.awaitTermination(60000,TimeUnit.SECONDS)),I am instantiating the thread pool again.


public class SampleMain {

public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i=0;i<10;i++){ 
   executorService.execute(new SampleRunnable(i));
}

executor.shutdown();
}

Sounds like the problem is, you want to throttle the main thread, so that it does not get ahead of the workers. If that's the case, then consider explicitly constructing a ThreadPoolExecutor instance instead of calling Executors.newFixedThreadPool() .

That class has several different constructors, and most of them allow you to supply your own blocking queue. If you create an ArrayBlockingQueue with a limited size, then every time the queue becomes full, the main thread will be automatically blocked until a worker makes room by taking another task.

final int work_queue_size = 30;
BlockingQueue work_queue = new ArrayBlockingQueue(work_queue_size);
ExecutorService executor = new ThreadPoolExecutor(..., work_queue);

for (int i=0;i<10;i++){ 
    executorService.execute(new SampleRunnable(i));
}
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM