Home > Software engineering >  Alternative to ScheduledThreadPoolExecutor to avoid excessive thread allocation
Alternative to ScheduledThreadPoolExecutor to avoid excessive thread allocation

Time:09-16

I'm using ScheduledThreadPoolExecutor to schedule a large number of tasks to run evenly over an hour.

There will be tens of thousands of tasks, and this may grow during surges in demand to hundreds of thousands or millions.

Normally, with a ThreadPoolExecutor, I can set the corePoolSize to a reasonable figure, such as 10 threads, and then allow the pool to grow as necessary.

However, the documentation for ScheduledThreadPoolExecutor says that:

because it acts as a fixed-sized pool using corePoolSize threads and an unbounded queue, adjustments to maximumPoolSize have no useful effect

This means that if I set the corePoolSize to 10, it will be capped at 10 threads. If I set the corePoolSize to 1000, it will instantly allocate 1000 threads, even though it may never reach that many active threads.

Is there an alternative to ScheduledThreadPoolExecutor that will let me set a high maximum thread count, without allocating all of those threads instantly?

FYI, the reason for the need for a huge active thread count is that the threads are I/O bound, and not CPU bound.

CodePudding user response:

Is there an alternative to ScheduledThreadPoolExecutor that will let me set a high maximum thread count

Yes!

Well… maybe. Perhaps in the near future.

Project Loom

Project Loom is an effort in the making for a few years now to bring new capabilities to the concurrency facilities in Java.

  • Virtual Threads are being previewed now in Java 19. Each conventional thread in Java maps one-to-one to a thread provided and managed by the host operating system. OS threads are expensive in terms of scheduling, CPU utilization, and memory. Virtual threads, in contrast, are mapped many-to-one to a host OS thread. The JVM switches between virtual threads when detecting Java code that blocks. As a result you can have many more threads, millions even, rather than several or dozens.
  • Structured Concurrency is being incubated in Java 19. Basically this provides an easy way to submit and track a bunch of tasks across a bunch of threads. This “treats multiple tasks running in different threads as a single unit of work“, to quote JEP 428.

Virtual threads promise to be generally appropriate to most tasks in most apps commonly implemented in Java. There are two caveats: (a) Virtual threads are contra-indicated for tasks that are CPU-bound, continually computing with no blocking (no user-interface interaction, no logging, no disk access, no network access, no database access, etc.). An example would be video-encoding; for such work use conventional threads in Java. (b) Tasks that utilize constrained resources will need gate-keeping or throttling.

In your scenario, I expect you will not need to concern yourself with setting thread pool size. Virtual threads handle that automatically in common cases. And you’ll not need to distribute the tasks over time to avoid overloading the machine — again, virtual threads manage that automatically in common cases.

For more info on Project Loom, see the many articles available on the Web, and the many talks and interviews with the Loom team members including Ron Pressler and Alan Bateman. And I recommend multiple recent videos on the YouTube channel JEP Café.

CodePudding user response:

The answer was simple:

I replaced

scheduledThreadPoolExecutor.schedule(task, delay, timeUnit);

with

scheduledThreadPoolExecutor.schedule(()->executorService.submit(task), delay, timeUnit);

where executorService is a ThreadPoolExecutor that is allowed to have a corePoolSize that is different from the maxPoolSize

  • Related