Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ScheduledExecutorService one thread many tasks

I am new to ExecutorService and wonder why following code prints correctly "10 15", even though I have created only one thread to process the timeouts? Why can I call schedule many times without previous tasks being cancelled on a single thread executor?

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class TestExecutorService implements Runnable {
    public static ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor();
    private int delay;


    public TestExecutorService(int delay) {
        this.delay = delay;
    }

    public void run () {
        System.out.println(delay);
    }

    public static void main (String[] args) {
        SERVICE.schedule(new TestExecutorService(10), 10, TimeUnit.SECONDS);
        SERVICE.schedule(new TestExecutorService(15), 15, TimeUnit.SECONDS);

        SERVICE.shutdown();
    }
}
like image 267
Nikolay Kuznetsov Avatar asked Dec 18 '12 06:12

Nikolay Kuznetsov


2 Answers

From the Javadocs:

Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time.

The difference between "processing timeouts" and "task execution" is the key to the answer. You assume that "single-threaded" means "processing only one timeout at a time", but it really means "executing only one task at a time". All the timeouts are processed simultaneously, but if one timeout is reached before a task stops executing, it will have to wait for the other one to finish before it can execute.

like image 188
Brian Avatar answered Sep 20 '22 12:09

Brian


Reading the Javadoc would be very helpful in this case. It does explain that though the executor will be created with a single thread, it will be operating with an unbounded queue. This means that you can submit multiple tasks to the executor and they will be queued up to run one after the other, up to the maximum bounds of the queue (which in this case is infinity) or until the JVM runs out of resources.

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.

In your example your two tasks get queued up, and run sequentially one after the other, which is why you get the (expected) output.

like image 20
Perception Avatar answered Sep 20 '22 12:09

Perception