billoot
billoot

Reputation: 47

How does interrupting a future work with single thread executors?

How does Executor.newSingleThreadExecutor() behave if I am frequently scheduling tasks to run that are being cancelled with future.cancel(true);?

Does the single thread spawned by the executor get interrupted (so the future code needs to clear the interrupt), or does the interrupt flag get automatically cleared when the next future starts up.

Does the Executor need to spawn an additional thread on every interrupt to be used by the remaining task queue?

Is there a better way?

Upvotes: 1

Views: 1378

Answers (2)

Tamas Hegedus
Tamas Hegedus

Reputation: 29916

Good question, I don't find this documented anywhere, so I would say it is implementation dependent.

For example OpenJDK does reset the interrupted flag before every executed task:

// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted.  This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
     (Thread.interrupted() &&
      runStateAtLeast(ctl.get(), STOP))) &&
    !wt.isInterrupted())
    wt.interrupt();

Snippet from from OpenJDK jdk8u ThreadPoolExecutor#runWorker source.

Upvotes: 1

Kannan Ekanath
Kannan Ekanath

Reputation: 17601

The following sample program demonstrates that the interrupt is called on the thread if you call the cancel method with true. You can even see that it is reusing the same thread. The cancel returns a boolean which indicates if the cancellation was successful. The javadoc of this method is also clear enough.

class Task implements Callable<String> {

    @Override
    public String call() throws Exception {
        try {
            System.out.println("Thread name = " + Thread.currentThread().getName());
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
            return "Interruped";
        }
        return "X";
    }
}
public class Testy {


    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService =
                Executors.newSingleThreadExecutor();
        int count = 0;
        while (true) {
            System.out.println("Iteration " + count++);
            Future<String> submit = executorService.submit(new Task());
            Thread.sleep(500);
            submit.cancel(true);
        }

    }
}

Output looks like below

Iteration 0
Thread name = pool-1-thread-1
Iteration 1
Interrupted
Thread name = pool-1-thread-1
Iteration 2
Interrupted

Upvotes: 1

Related Questions