简体   繁体   中英

Thread to ask for new tasks from executorservice

I currently have the main method which collects tasks. After the tasks are collected, the ExecutorService is being called with fixed thread pool size. The tasks are iterated and submitted to the executor.

But I need to refresh the tasks and if there is any new tasks available I am adding it to the executor. But if one of the thread is free without any tasks to be allocated from the queue, I want that thread to manually notify my main thread to refresh the events and submit to executor even before the manual refresh is happening from my end. How can i achieve this. Thanks

Sample Code

public class Sample{
   Map<String, List<Integer>> tasks;
   ThreadPoolExecutor executor;

   public static void main(String[] args) {
     executor = Executors.newFixedThreadPool(2);
     tasks = Collections.synchronizedMap(new HashMap<String, List<Integer>>());
     tasks =  Tasks.refresh(); //This will get me a new set of data to be processed
     invokeexecutor();
   }
   public void invokeexecutor(){
      for(String key: tasks.keyset())
      {
       executor.submit(new TaskRunnable(tasks.get(key));
      }
      tasks.clear(); //Remove the allocated tasks from the collection
   }
}

public class TaskRunnable implements Runnable{
   public void run(){
        //Do some logic
   }
}

In this case I want my data in the tasks to be continuously refreshed after 10 seconds lets say or if any of the executor thread is free this refresh must happen and a new runnable mus tbe assinged to the thread.

But if one of the thread is free without any tasks to be allocated from the queue, I want that thread to manually notify my main thread to refresh the events and submit to executor even before the manual refresh is happening from my end. How can i achieve this.

There are a couple of ways you can achieve this easily. One way is to create the `ThreadPoolExecutor' yourself.

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
                                             new LinkedBlockingQueue<Runnable>());

Then have a polling thread that watches the ThreadPoolExecutor class to determine if there are any free threads. Something like:

 while (!Thread.currentThread().isInterrupted()) {
     // sleep a bit
     Thread.sleep(1000);
     if (executor.getActiveCount() < 2) {
        // add tasks here
     }
 }

A polling thread is a bit gross however. Another idea which is a bit simpler would be to use a fixed size queue of tasks and then always be trying to add the tasks to the list. This will block if the queue is full. Something like:

// create a limited blocking queue
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
                                             new LinkedBlockingQueue<Runnable>(10));
 while (!Thread.currentThread().isInterrupted()) {
     // add tasks here which will block if too many in the queue
 }

You can try to override afterExecute method in ThreadPoolExecutor. It is called when a thread in a pool executed a task.

class MyThreadPoolExecutor extends ThreadPoolExecutor {
    public MyThreadPoolExecutor {
        super(/*Call one of TheadPoolExecutor constructors*/)
    }

    protected afterExecute(Runnable r, Throwable t) {
        // Notify main thread here
    }
}

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