JDK-8350493 : Improve performance of delayed task handling
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 25
  • Submitted: 2025-02-21
  • Updated: 2025-06-18
  • Resolved: 2025-03-31
Related Reports
CSR :  
Duplicate :  
Duplicate :  
Description
Summary
-------

Improve the performance of delayed task handling with an update to  `java.util.concurrent.ForkJoinPool` to implement `ScheduledExecutorService`.


Problem
-------

In common network-related applications, delayed tasks to handle timeouts are scheduled but are usually cancelled. This may lead to excessive contention and avoidable locking, especially with virtual threads, in turn using `ForkJoinPool`. `ScheduledThreadPoolExecutor` is ill-suited for many (if not most) of its applications, and is a performance bottleneck with virtual threads and ` CompletableFuture`.


Solution
--------

Lazily connect  support for `ScheduledExecutorService` to any `ForkJoinPool` instance, this includes the common pool.

In API terms  `java.util.concurrent.ForkJoinPool` is updated to implement  `ScheduledExecutorService`, thus adding 3 methods to its API:

```
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
```

Three other methods added:  to submit a task with a timeout, a method to disable delayed tasks on shutdown, and a method to get an estimate of the number of delayed tasks that are schedueld.

```
public <V> ForkJoinTask<V> submitWithTimeout(Callable<V> callable, 
                                             long timeout, TimeUnit unit,
                                             Consumer<? super ForkJoinTask<V>> timeoutAction)
public void cancelDelayedTasksOnShutdown() 
public long getDelayedTaskCount()
```

`CompletableFuture` is updated for the corner case that the ForkJoinPool common pool is configured with zero parallelism. The async methods were to create a new `Thread` for each async task. This is changed, in a backward compatible way, to consistently use the common pool.

Finally, while in the area, the description of the `corePoolSize` parameter in the 10-arg `ForkJoinPool` constructor is changed to specify that the parameter is ignored. The parameter is already ignored, this change just aligns the spec with the long standing implementation.


Specification
-------------

A zip file is attached with the API diffs.



Comments
Moving updated request to Approved.
31-03-2025

The attached apidiff-20250327.zip is the API diffs for what is in the PR right now.
27-03-2025

If there were any changes to the spec from the PR, please update the CSR and Finalize the request if you think it is ready for re-review.
27-03-2025

I don't think there would be any value to adding implSpec to these methods. It should be rare to extend ForkJoinPool and if someone is extending and overriding any of the new methods proposed here then there isn't anything further to say in an implSpec.
26-03-2025

I don't think there is any relevant implSpec for these. The only reason there is any javadoc at all (vs inheriting it all) is to explicitly (although not very interestingly) say when exceptions occur wrt shutdown, which ScheduledExecutorService should probably have mentioned but doesn't.
24-03-2025

Moving to Provisional, not Approved. [~dl] and [~alanb], since ForkJoinPool is subclassable, should the methods added from ScheduledExecutorService have any implSpec tags to describe their self-use or other relevant implementation properties?
24-03-2025