Biene Maja
Biene Maja

Reputation: 323

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"?

Upvotes: 8

Views: 15908

Answers (3)

Grigory Kislin
Grigory Kislin

Reputation: 18030

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

Upvotes: 1

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

Yes, I would suggest using a single scheduler.

Executors.newCachedThreadPool() returns an ExecutorService, not a ScheduledExecutorService, so I don't think that will work for you. I'd stick with newScheduledThreadPool()

Upvotes: 0

casablanca
casablanca

Reputation: 70721

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.

Upvotes: 4

Related Questions