Reputation: 27880
I'm using a single threaded ScheduledExecutorService
in order to process some Runnable
tasks. When my Runnable
has finished its work, it reschedules itself in the ScheduledExecutorService
with a variable delay. This happens indefinitely until the Runnable
catches an Exception
.
public class Runner {
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
public void startWorking() {
// Single-shot start
service.submit(new Task(service));
}
public void stopWorking() {
service.shutDown();
// Do some other stuff
}
private static final class Task implements Runnable {
ScheduledExecutorService service;
private Task(ScheduledExecutorService service) {
this.service = service;
}
@Override
public void run() {
try {
// Do some work...
service.schedule(this, variableDelay, TimeUnit.SECONDS);
}
catch(SomethingHappenedException e){
// Shutdown service
}
}
}
}
Can I shutdown()
or shutdownNow()
the ExecutorService
safely from Task.run()
? Something doesn't look right if the thread will be provoking an interrupt to itself.
When an exception is caught while executing Task
, I'd like to shutdown
the service
, ideally calling Runner.stopWorking()
.
I know I could use a Callable
instead and let Runner
manage reschedulings, but I'd like to keep this structure (Runner
will have more analogous service
s, so an infinite loop just doesn't look right there).
I guess I could subclass ScheduledThreadPoolExecutor
to override afterExecute
and handle shutdown there, using a reference to Runner
.
public class Runner {
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1){
protected void afterExecute(Runnable r, Throwable t) {
if (t != null) {
Runner.this.stopWorking();
}
};
// ...
}
My concern with this approach is, if afterExecute
will be invoked by the thread that ran the Task
, this would have the same effects as calling shutDown()
from Task.run()
itself.
Is there any other alternative approach to this?
Upvotes: 1
Views: 2186
Reputation: 32535
Can I shutdown() or shutdownNow() the ExecutorService safely from Task.run()? Something doesn't look right if the thread will be provoking an interrupt to itself.
shutdown()
will not interrupt already running tasks but will prevent new task from beeing submited.
shutdownNow()
doesn't interrupt running tasks either, but "signals" all workers that they should be terminated. It is up to Thread
implementation (or rather Runnable
itself) will it honor such signal (Thread.isTerminated()
as I remember) or not.
And yes, it is perfectly fine for thread to signal itself to be terminated. So it is safe to shutdown()
executor from running task.
Upvotes: 5