Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple tasks with ScheduledExecutorService

i currently have a list of classes every class starts a scheduler like this:

private ScheduledFuture<?> myTask;
private ScheduledExecutorService scheduler;

public startScheduler() {
scheduler = Executors.newScheduledThreadPool( 1 );
    myTask = scheduler.scheduleAtFixedRate(new Runnable() {
          // doing work here
     },
          delay,
          interval,
          TimeUnit.MILLISECONDS );
}

So every class basically starts it's own scheduler and only has one task. But as i understand now a scheduler can take and run more tasks in parallel. The tasks (or in my current program the schedulers) have different delay and interval values and the number of schedulers started is unknown to me (cause the user can start new ones and stop running ones). All schedulers run in parallel. So should i change my code in order to use only one scheduler? Should I prefer the "CachedThreadPool"?

like image 344
Biene Maja Avatar asked Feb 07 '12 03:02

Biene Maja


2 Answers

Yes, you can use just one pool to schedule all your tasks. Also, if you need the ability to schedule tasks at time intervals as you are currently doing, you should stick with newScheduledThreadPool because newCachedThreadPool returns only an ExecutorService interface and not ScheduledExecutorService.

like image 178
casablanca Avatar answered Sep 30 '22 07:09

casablanca


I see it is surprise not only for me: ScheduledThreadPoolExecutor has a fixed threadpool size:

No. From http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html:

.... it acts as a fixed-sized pool using corePoolSize threads ...

Some other related links:

Why is there no scheduled cached thread pool provided by the Java Executors class?

http://coding.tocea.com/java/dmi_futile_attempt_to_change_maxpool_size_of_scheduled_thread_pool_executor/

Why does ScheduledThreadPoolExecutor only accept a fixed number of threads?

Have a look at test result:

public class AsyncExecutorTest {
   private static final ScheduledThreadPoolExecutor SCH_EXECUTOR = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
   private static final ExecutorService EXECUTOR = (ExecutorService) Executors.newCachedThreadPool();
   public static final int NUMBER = 10;

   @Test
   public void testSubmit() throws Exception {
      submit(EXECUTOR);
      submit(SCH_EXECUTOR);

      SCH_EXECUTOR.setMaximumPoolSize(100);
      submit(SCH_EXECUTOR);
      SCH_EXECUTOR.setCorePoolSize(100);
      submit(SCH_EXECUTOR);
   }

   private void submit(ExecutorService exe) throws InterruptedException {
      long start = System.currentTimeMillis();
      final CountDownLatch cdt = new CountDownLatch(NUMBER);
      for (int i = 0; i < NUMBER; i++) {
          exe.submit(new Runnable() {
          @Override
             public void run() {
                try {
                    Thread.sleep(1000);
                    cdt.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
          });
      }
      cdt.await();
      System.out.println(System.currentTimeMillis() - start);
   }
}

1002

5004

5001

1006

Suggested solution is:

 scheduledExecutor = new ScheduledThreadPoolExecutor(150); //max thread
 scheduledExecutor.setKeepAliveTime(10, TimeUnit.SECONDS);
 scheduledExecutor.allowCoreThreadTimeOut(true);  // allow terminate core idle threads

From example can be seen that max thread pool size could be changed not by setMaxPoolSize but by setCorePoolSize

like image 34
Grigory Kislin Avatar answered Sep 30 '22 07:09

Grigory Kislin