ScheduledExecutorService is not shutting down - java

I need to stop all the scheduled runnables when shutting down this executor I save the scheduled futures in a list when using execute(Runnable runnable), however, this does not work, the runnables are still being runned after calling shutdown but i'm in fact stopping them using scheduledFutures.forEach(scheduledFuture -> scheduledFuture.cancel(false)) in that method, why does this happen?.
public class ThreadPool {
private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private final List<ScheduledFuture<?>> scheduledFutures = new ArrayList<>();
public ThreadPool(ScheduledThreadPoolExecutor scheduledThreadPoolExecutor) {
this.scheduledThreadPoolExecutor = scheduledThreadPoolExecutor;
}
public void execute(Runnable runnable) {
scheduledFutures.add(
scheduledThreadPoolExecutor.scheduleWithFixedDelay(runnable, 0, 20, TimeUnit.SECONDS));
}
public void shutdown() {
scheduledFutures.forEach(scheduledFuture -> scheduledFuture.cancel(false));
scheduledThreadPoolExecutor.shutdown();
try {
if (scheduledThreadPoolExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
return;
}
scheduledThreadPoolExecutor.shutdownNow();
} catch (Exception exception) {
Thread.currentThread().interrupt();
}
}

Related

Why is a Runnable still executed in a pausable thread pool executor after the executor is shut down?

I have a pausable thread pool executor implementation just like in the documentation of the ThreadPoolExecutor class. I have a simple test that does the following:
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
public static PausableThreadPoolExecutor newSingleThreadExecutor() {
return new PausableThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/** isPaused */
private boolean isPaused;
/** pauseLock */
private ReentrantLock pauseLock = new ReentrantLock();
/** unpaused */
private Condition unpaused = this.pauseLock.newCondition();
public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
#Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
this.pauseLock.lock();
try {
while (this.isPaused) {
this.unpaused.await();
}
} catch (InterruptedException ie) {
t.interrupt();
} finally {
this.pauseLock.unlock();
}
}
public void pause() {
this.pauseLock.lock();
try {
this.isPaused = true;
} finally {
this.pauseLock.unlock();
}
}
public void resume() {
this.pauseLock.lock();
try {
this.isPaused = false;
this.unpaused.signalAll();
} finally {
this.pauseLock.unlock();
}
}
public static void main(String[] args) {
PausableThreadPoolExecutor p = PausableThreadPoolExecutor.newSingleThreadExecutor();
p.pause();
p.execute(new Runnable() {
public void run() {
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
});
p.shutdownNow();
}
}
Interestingly the call to shutDownNow will cause the Runnable to run. Is this normal? As I understand the shutDownNow will try to stop the actively executing tasks by interrupting them. But the interrupt seems to wake up the task an execute it. Can someone explain this ?
Interestingly the call to shutDownNow will cause the Runnable to run. Is this normal?
Not sure it is "normal" but it is certainly expected given your code. In your beforeExecute(...) method I see the following:
this.pauseLock.lock();
try {
while (this.isPaused) {
this.unpaused.await();
}
} catch (InterruptedException ie) {
t.interrupt();
} finally {
this.pauseLock.unlock();
}
The job will lopp waiting for the isPaused boolean to be set to false. However, if the job is interrupted the this.unpaused.await() will throw InterruptedException which breaks out of the while loop, the thread is reinterrupted which is always a good pattern, beforeExecute() returns, and the job is allowed to execute. Interrupting a thread doesn't kill it unless you have specific code to handle the interruption.
If you want to stop the job when it is interrupted then you could throw a RuntimeException in the beforeExecute() handler when you see that the job as been interrupted:
} catch (InterruptedException ie) {
t.interrupt();
throw new RuntimeException("Thread was interrupted so don't run");
A cleaner approach might be to check to see if you are interrupted in the run() method and then exit:
public void run() {
if (Thread.currentThread().isInterrupted()) {
return;
}
...

Java - Time limited tasks in a threadpool finish earnier than expected

I have a problem understanding the bug. I have a code which runs tasks in a thread pool. But the time of execution of a single task is limited. Here is the code:
public static abstract class CustomRunnable implements Runnable {
private CountDownLatch latch;
public void setLatch(CountDownLatch latch) {
this.latch = latch;
}
protected void threadFinished() {
latch.countDown();
}
}
And executions:
CountDownLatch latch = new CountDownLatch(threads.size());
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
try {
for(CustomRunnable thread : threads) {
thread.setLatch(latch);
Future<?> future = executor.submit(thread);
canceller.schedule(new Runnable() {
#Override
public void run() {
future.cancel(true);
thread.threadFinished();
}
}, 1, TimeUnit.MINUTES);
}
latch.await();
executor.shutdown();
canceller.shutdown();
}
catch(InterruptedException e) {
e.printStackTrace();
}
But latch.await(); fires much more earlier than expected (this code is used in a few places). Are there any ideas how to fix that? Thanks!

Java timeout multiple tasks in parallel

What is the best practice approach to launch a pool of 1000's of tasks (where up to 4 should be able to execute in parallel) and automatically timeout them if they take more than 3 seconds (individually)?
While I found that ExecutorService seems to be helpful (see SSCE from another post below), I don't see how to make this work for multiple tasks running in parallel (as the future.get(3, TimeUnit.SECONDS) is executing on the same thread than the one launching the tasks, hence no opportunity to launch multiple tasks in parallel):
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
Thanks!
If you have to monitor each task to kill it when it exceeds the timeout period, either
the task itself has to keep track of time and quit appropriately, OR
you have to create a second watchdog thread for every task. The watchdog thread sets a timer and sleeps, waking up after the timeout interval expires and then terminating the task if it's still running.
This is a tricky one. Here’s what I came up with:
public class TaskQueue<T> {
private static final Logger logger =
Logger.getLogger(TaskQueue.class.getName());
private final Collection<Callable<T>> tasks;
private final int maxTasks;
private int addsPending;
private final Collection<T> results = new ArrayList<T>();
private final ScheduledExecutorService executor;
public TaskQueue() {
this(4);
}
public TaskQueue(int maxSimultaneousTasks) {
maxTasks = maxSimultaneousTasks;
tasks = new ArrayDeque<>(maxTasks);
executor = Executors.newScheduledThreadPool(maxTasks * 3);
}
private void addWhenAllowed(Callable<T> task)
throws InterruptedException,
ExecutionException {
synchronized (tasks) {
while (tasks.size() >= maxTasks) {
tasks.wait();
}
tasks.add(task);
if (--addsPending <= 0) {
tasks.notifyAll();
}
}
Future<T> future = executor.submit(task);
executor.schedule(() -> future.cancel(true), 3, TimeUnit.SECONDS);
try {
T result = future.get();
synchronized (tasks) {
results.add(result);
}
} catch (CancellationException e) {
logger.log(Level.FINE, "Canceled", e);
} finally {
synchronized (tasks) {
tasks.remove(task);
if (tasks.isEmpty()) {
tasks.notifyAll();
}
}
}
}
public void add(Callable<T> task) {
synchronized (tasks) {
addsPending++;
}
executor.submit(new Callable<Void>() {
#Override
public Void call()
throws InterruptedException,
ExecutionException {
addWhenAllowed(task);
return null;
}
});
}
public Collection<T> getAllResults()
throws InterruptedException {
synchronized (tasks) {
while (addsPending > 0 || !tasks.isEmpty()) {
tasks.wait();
}
return new ArrayList<T>(results);
}
}
public void shutdown() {
executor.shutdown();
}
}
I suspect it could be done more cleanly using Locks and Conditions instead of synchronization.

JAVA pass a method from outside class to the ThreadPool.submit()

I don't have previous experience with JAVA's concurrency, but ever done the same in C#.
My task
To create a "worker" class for easy multi-threading (creating continuous threads) managing in my applications.
what i want to have as result(usage example):
Worker worker = new Worker();
worker.threadCount = 10;
worker.doWork(myMethod);
worker.Stop();
to be able to use it in any class in my app, accepting 'void' methods as 'worker.doWork(myMethod);' argument.
What did i done from my researches on question:
class Worker
package commons.Threading;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class Worker {
static Boolean IsRunning = true;
public static int threadCount = 2;
static ExecutorService threadPool = new ErrorReportingThreadPoolExecutor(threadCount);
public void doWork(**argument method**) throws IOException, InterruptedException {
while (IsRunning) {
threadPool.submit(new Runnable() {
**argument method**
});
Thread.sleep(1000);
}
}
public static void Stop(){
IsRunning = false;
threadPool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
threadPool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
threadPool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
ErrorReportingThreadPoolExecutor
package commons.Threading;
import java.util.concurrent.*;
public class ErrorReportingThreadPoolExecutor extends ThreadPoolExecutor {
public ErrorReportingThreadPoolExecutor(int nThreads) {
super(nThreads, nThreads,
0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
#Override
protected void afterExecute(Runnable task, Throwable thrown) {
super.afterExecute(task, thrown);
if (thrown != null) {
// an unexpected exception happened inside ThreadPoolExecutor
thrown.printStackTrace();
}
if (task instanceof Future<?>) {
// try getting result
// if an exception happened in the job, it'll be thrown here
try {
Object result = ((Future<?>)task).get();
} catch (CancellationException e) {
// the job get canceled (may happen at any state)
e.printStackTrace();
} catch (ExecutionException e) {
// some uncaught exception happened during execution
e.printStackTrace();
} catch (InterruptedException e) {
// current thread is interrupted
// ignore, just re-throw
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) throws InterruptedException {
// replace
// ExecutorService threadPool = Executors.newFixedThreadPool(2);
// with
ExecutorService threadPool = new ErrorReportingThreadPoolExecutor(2);
while (true) {
threadPool.submit(new Runnable() {
#Override public void run() {
System.out.println("Job is running...");
if (Math.random() < 0.5) {
int q = 1 / 0;
}
System.out.println("Job finished.");
}
});
Thread.sleep(1000);
}
}
}
So, the question is - how do i pass 'void' method from outside class here threadPool.submit(new Runnable() { here });
You could pass the Runnable itself is a parameter,
public void doWork(Runnable runnable) throws IOException, InterruptedException {
while (IsRunning) {
threadPool.submit(runnable);
Thread.sleep(1000);
}
}
Runnable is a functional interface,it has a single method run that takes no-param and returns void, and hence you can use it as a function.
Runnable runnable = new Runnable(){
public void run(){
// do work
}
};
doWork(runnable);
You can express it more concisely if you are on Java 1.8
Runnable runnable = ()->{/**do work*/};
doWork(runnable);

Handling Exceptions for ThreadPoolExecutor

I have the following code snippet that basically scans through the list of task that needs to be executed and each task is then given to the executor for execution.
The JobExecutor in turn creates another executor (for doing db stuff...reading and writing data to queue) and completes the task.
JobExecutor returns a Future<Boolean> for the tasks submitted. When one of the task fails, I want to gracefully interrupt all the threads and shutdown the executor by catching all the exceptions. What changes do I need to do?
public class DataMovingClass {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static final ThreadLocal<Integer> uniqueNumber = new IDGenerator();
ThreadPoolExecutor threadPoolExecutor = null ;
private List<Source> sources = new ArrayList<Source>();
private static class IDGenerator extends ThreadLocal<Integer> {
#Override
public Integer get() {
return uniqueId.incrementAndGet();
}
}
public void init(){
// load sources list
}
public boolean execute() {
boolean succcess = true ;
threadPoolExecutor = new ThreadPoolExecutor(10,10,
10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("DataMigration-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
List<Future<Boolean>> result = new ArrayList<Future<Boolean>>();
for (Source source : sources) {
result.add(threadPoolExecutor.submit(new JobExecutor(source)));
}
for (Future<Boolean> jobDone : result) {
try {
if (!jobDone.get(100000, TimeUnit.SECONDS) && success) {
// in case of successful DbWriterClass, we don't need to change
// it.
success = false;
}
} catch (Exception ex) {
// handle exceptions
}
}
}
public class JobExecutor implements Callable<Boolean> {
private ThreadPoolExecutor threadPoolExecutor ;
Source jobSource ;
public SourceJobExecutor(Source source) {
this.jobSource = source;
threadPoolExecutor = new ThreadPoolExecutor(10,10,10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("Job Executor-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
}
public Boolean call() throws Exception {
boolean status = true ;
System.out.println("Starting Job = " + jobSource.getName());
try {
// do the specified task ;
}catch (InterruptedException intrEx) {
logger.warn("InterruptedException", intrEx);
status = false ;
} catch(Exception e) {
logger.fatal("Exception occurred while executing task "+jobSource.getName(),e);
status = false ;
}
System.out.println("Ending Job = " + jobSource.getName());
return status ;
}
}
}
When you submit a task to the executor, it returns you a FutureTask instance.
FutureTask.get() will re-throw any exception thrown by the task as an ExecutorException.
So when you iterate through the List<Future> and call get on each, catch ExecutorException and invoke an orderly shutdown.
Since you are submitting tasks to ThreadPoolExecutor, the exceptions are getting swallowed by FutureTask.
Have a look at this code
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}
From above code, it is clear that setException method catching Throwable. Due to this reason, FutureTask is swallowing all exceptions if you use "submit()" method on ThreadPoolExecutor
As per java documentation, you can extend afterExecute() method in ThreadPoolExecutor
protected void afterExecute(Runnable r,
Throwable t)
Sample code as per documentation:
class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
You can catch Exceptions in three ways
Future.get() as suggested in accepted answer
wrap entire run() or call() method in try{}catch{}Exceptoion{} blocks
override afterExecute of ThreadPoolExecutor method as shown above
To gracefully interrupt other Threads, have a look at below SE question:
How to stop next thread from running in a ScheduledThreadPoolExecutor
How to forcefully shutdown java ExecutorService
Subclass ThreadPoolExecutor and override its protected afterExecute (Runnable r, Throwable t) method.
If you're creating a thread pool via the java.util.concurrent.Executors convenience class (which you're not), take at look at its source to see how it's invoking ThreadPoolExecutor.

Categories

Resources