Reputation: 183
Say I have this bloated example. What I would expect to happen is to get a couple of numbers in the console around three times, then I'd expect the "The task is stopped" line to be printed, and then I'd get no more numbers.
So I'd like to stop a task from being executed. So far I've tried to cancel(true)
the future, executor.shutdownNow)(
and executor.shutdown()
the executor, but none of those lead to a behavior that I've described above. Am I missing something? Is there a way to cancel this task?
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.setRemoveOnCancelPolicy(true);
final int rareNumber = 302330233;
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
int x = 0;
while (true) {
x++;
if(x % rareNumber == 0) {
System.out.println(x);
}
}
}, 1, 2, TimeUnit.SECONDS);
Thread.sleep(3_000);
// I'd like to stop a task here.
System.out.println("The task is stopped");
Upvotes: 0
Views: 1090
Reputation: 16910
There are a couple of things you should consider in your code :
ExecutorService
docs :void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
If you want to make your task cancellable there are 2 common ways to do it :
Thread.currentThread().isInterrupted()
status in a loopInterruptedException
you can handle this exception. It will be thrown when the Thread is interrupted.as you have set executor.setRemoveOnCancelPolicy(true);
the Threads will not be be recreated if they are Interrupted. If you did not set this flag - it is a good idea to preserve the interruption status, as you are not the owner of those threads and you do not know what interruption means to them. But you are not using any methods that can throw InterruptedException
so it is ok.
Upvotes: 1
Reputation: 2111
First, when you find a correct number at one execution, you should break that while
loop to finish that execution cycle.
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
int x = 0;
while (true) {
x++;
if(x % rareNumber == 0) {
System.out.println(x);
break;
}
}
}, 1, 2, TimeUnit.SECONDS);
Then you can cancel the future as follows to stop the fixed-rate scheduler.
Thread.sleep(3_000);
// I'd like to stop a task here.
future.cancel(true);
System.out.println("The task is stopped");
Upvotes: 1
Reputation: 15086
The correct method is executor.shutdownNow()
. This causes the thread to be interrupted.
However your thread is not be waiting / sleeping at that time, so you don't get IterruptedException
so you need to check Thread.intrrupted()
flag:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.setRemoveOnCancelPolicy(true);
final int rareNumber = 302330233;
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
int x = 0;
while (true) {
x++;
if(x % rareNumber == 0) {
System.out.println(x);
}
if (Thread.interrupted()) {
return;
}
}
}, 1, 2, TimeUnit.SECONDS);
Thread.sleep(3_000);
executor.shutdownNow();
// I'd like to stop a task here.
System.out.println("The task is stopped");
Upvotes: 1