What is terminating my Java ExecutorService - java

I originally saw this issue with a more complex subclass of ThreadPoolExecutor, but I have simplified so now contains not much more than some additional debugging, and still get the same problem.
import com.jthink.songkong.cmdline.SongKong;
import com.jthink.songkong.ui.MainWindow;
import com.jthink.songkong.util.SongKongThreadFactory;
import java.util.concurrent.*;
import java.util.logging.Level;
public class TimeoutThreadPoolExecutor extends ThreadPoolExecutor
{
/**
* Uses the default CallerRunsPolicy when queue is full
* #param workerSize
* #param threadFactory
* #param queue
*/
public TimeoutThreadPoolExecutor(int workerSize, ThreadFactory threadFactory, LinkedBlockingQueue<Runnable> queue)
{
super(workerSize, workerSize, 0L, TimeUnit.MILLISECONDS, queue, threadFactory, new CallerRunsPolicy());
}
/**
* Allow caller to specify the RejectedExecutionPolicy
* #param workerSize
* #param threadFactory
* #param queue
* #param reh
*/
public TimeoutThreadPoolExecutor(int workerSize, ThreadFactory threadFactory, LinkedBlockingQueue<Runnable> queue, RejectedExecutionHandler reh)
{
super(workerSize, workerSize, 0L, TimeUnit.MILLISECONDS, queue, threadFactory, reh);
}
#Override
public <T> FutureCallable<T> newTaskFor(Callable<T> callable) {
return new FutureCallable<T>(callable);
}
/**
* Check not been paused
*
* #param t
* #param r
*/
#Override
protected void beforeExecute(Thread t, Runnable r) {
SongKong.checkIn();
}
/**
* After execution
*
* #param r
* #param t
*/
#Override
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)
{
MainWindow.logger.log(Level.SEVERE, "AFTER EXECUTE---" + t.getMessage(), t);
}
}
#Override
protected void terminated()
{
//All tasks have completed either naturally or via being cancelled by timeout task so close the timeout task
MainWindow.logger.severe("---Terminated:"+((SongKongThreadFactory)getThreadFactory()).getName());
MainWindow.userInfoLogger.severe("---Terminated:"+((SongKongThreadFactory)getThreadFactory()).getName());
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for(StackTraceElement ste:stackTrace)
{
MainWindow.logger.log(Level.SEVERE, ste.toString());
}
for(StackTraceElement ste:stackTrace)
{
MainWindow.userInfoLogger.log(Level.SEVERE, ste.toString());
}
}
#Override
public void shutdown()
{
MainWindow.logger.severe("---Shutdown:"+((SongKongThreadFactory)getThreadFactory()).getName());
MainWindow.userInfoLogger.severe("---Shutdown:"+((SongKongThreadFactory)getThreadFactory()).getName());
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for(StackTraceElement ste:stackTrace)
{
MainWindow.logger.log(Level.SEVERE, ste.toString());
}
for(StackTraceElement ste:stackTrace)
{
MainWindow.userInfoLogger.log(Level.SEVERE, ste.toString());
}
super.shutdown();
}
}
This ExecutorService is being used by the following class, that allow instance to asynchronously submit tasks, the ExecutorService should not be shutdown until all submitted tasks have completed.
package com.jthink.songkong.analyse.analyser;
import com.jthink.songkong.preferences.GeneralPreferences;
import com.jthink.songkong.ui.MainWindow;
import com.jthink.songkong.util.SongKongThreadFactory;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
/**
* Sets a timeout of each task submitted and cancel them if take longer than the timeout
*
* The timeout is set to 30 minutes, we only want to call if really broken, it should not happen under usual circumstances
*/
public class MainAnalyserService extends AnalyserService
{
//For monitoring/controlling when finished
private final AtomicInteger pendingItems = new AtomicInteger(0);
private final CountDownLatch latch = new CountDownLatch(1);
//If task has not completed 30 minutes after it started (added to queue) then it should be cancelled
private static final int TIMEOUT_PER_TASK = 30;
private static MainAnalyserService mas;
public static MainAnalyserService getInstanceOf()
{
return mas;
}
public static MainAnalyserService create(String threadGroup)
{
mas = new MainAnalyserService(threadGroup);
return mas;
}
public MainAnalyserService(String threadGroup)
{
super(threadGroup);
initExecutorService();
}
/**
Configure thread to match cpus but even if single cpu ensure have at least two threads to protect against
scenario where there is only cpu and that thread is waiting on i/o rather than being cpu bound this would allow
other thread to do something.
*/
#Override
protected void initExecutorService()
{
int workerSize = GeneralPreferences.getInstance().getWorkers();
if(workerSize==0)
{
workerSize = Runtime.getRuntime().availableProcessors();
}
//Even if only have single cpu we still have multithread so we dont just have single thread waiting on I/O
if(workerSize< MIN_NUMBER_OF_WORKER_THREADS)
{
workerSize = MIN_NUMBER_OF_WORKER_THREADS;
}
MainWindow.userInfoLogger.severe("Workers Configuration:"+ workerSize);
MainWindow.logger.severe("Workers Configuration:"+ workerSize);
executorService = new TimeoutThreadPoolExecutor(workerSize,
new SongKongThreadFactory(threadGroup),
new LinkedBlockingQueue<Runnable>(BOUNDED_QUEUE_SIZE),
TIMEOUT_PER_TASK,
TimeUnit.MINUTES,
new EnsureIncreaseCountIfRunOnCallingThread());
}
public AtomicInteger getPendingItems()
{
return pendingItems;
}
/**
* If queue is full this gets called and we log that we run task on local calling thread.
*/
class EnsureIncreaseCountIfRunOnCallingThread implements RejectedExecutionHandler
{
/**
* Creates a {#code CallerRunsPolicy}.
*/
public EnsureIncreaseCountIfRunOnCallingThread() { }
/**
* Executes task on calling thread, ensuring we increment count
*
* #param r the runnable task requested to be executed
* #param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown())
{
try
{
MainWindow.userInfoLogger.severe(">>SubmittedLocally:" + ((FutureCallable) r).getCallable().getClass().getName() + ":" + pendingItems.get());
r.run();
MainWindow.userInfoLogger.severe(">>CompletedLocally:" + ((FutureCallable) r).getCallable().getClass().getName() + ":" + pendingItems.get());
}
catch(Exception ex)
{
MainWindow.userInfoLogger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
}
/**
* Increase count and then Submit to ExecutorService
*
* #param callingTask
* #param task
*/
public void submit(Callable<Boolean> callingTask, Callable<Boolean> task) //throws Exception
{
//Ensure we increment before calling submit in case rejectionExecution comes into play
int remainingItems = pendingItems.incrementAndGet();
executorService.submit(task);
MainWindow.userInfoLogger.severe(">>Submitted:" + task.getClass().getName() + ":" + remainingItems);
}
public ExecutorService getExecutorService()
{
return executorService;
}
/**
* Must be called by Callable when it has finished work (or if error)
*
* #param task
*/
public void workDone(Callable task)
{
int remainingItems = pendingItems.decrementAndGet();
MainWindow.userInfoLogger.severe(">>WorkDone:" + task.getClass().getName() + ":" +remainingItems);
if (remainingItems == 0)
{
MainWindow.userInfoLogger.severe(">Closing Latch:");
latch.countDown();
}
}
/**
* Wait for latch to close, this should occur once all submitted aysync tasks have finished in some way
*
* #throws InterruptedException
*/
public void awaitCompletion() throws InterruptedException{
latch.await();
}
}
The calling Class has
//Just waits for all the async tasks on the list to complete/fail
analyserService.awaitCompletion();
MainWindow.userInfoLogger.severe(">MainAnalyser Completed");
For one customer the terminated() method was getting called even though there are still task that have not completed, and the executorservice has only been running for 8 minutes, and no tasks have timed out. I have also seen the problem locally
Debugging shows
UserLog
05/07/2019 11.29.38:EDT:SEVERE: ----G14922:The Civil War:8907617:American Songs of Revolutionary Times and the Civil War Era:NoScore
05/07/2019 11.29.38:EDT:SEVERE: >>Submitted:com.jthink.songkong.analyse.analyser.SongSaver:69
05/07/2019 11.29.38:EDT:SEVERE: >>WorkDone:com.jthink.songkong.analyse.analyser.DiscogsSongGroupMatcher:68
05/07/2019 11.29.38:EDT:SEVERE: >MainAnalyser Finished
05/07/2019 11.29.38:EDT:INFO: Stop
DebugLog
05/07/2019 11.29.38:EDT:TimeoutThreadPoolExecutor:terminated:SEVERE: ---Terminated:Worker
So we can see there are still 68 tasks to complete, and MainAnalyser has not closed the latch, yet threadpool executor has terminated
I overridden shutdown() to see if that is called and it is not,
terminate() is being called by runWorker(), runWorker() should continue in loop until queue is empty which it is not, but something seems to cause it to leave loop and the processWorkerExit() after doing some more checks eventually terminates the whole Executor (not just a worker thread)
10/07/2019 07.11.51:BST:MainAnalyserService:submit:SEVERE: >>Submitted:com.jthink.songkong.analyse.analyser.DiscogsSongGroupMatcher:809
10/07/2019 07.11.51:BST:MainAnalyserService:workDone:SEVERE: >>WorkDone:com.jthink.songkong.analyse.analyser.MusicBrainzSongGroupMatcher2:808
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: ---Terminated:Worker
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.lang.Thread.getStackTrace(Unknown Source)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: com.jthink.songkong.analyse.analyser.TimeoutThreadPoolExecutor.terminated(TimeoutThreadPoolExecutor.java:118)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.util.concurrent.ThreadPoolExecutor.tryTerminate(Unknown Source)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.util.concurrent.ThreadPoolExecutor.processWorkerExit(Unknown Source)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
10/07/2019 07.11.51:BST:TimeoutThreadPoolExecutor:terminated:SEVERE: java.base/java.lang.Thread.run(Unknown Source)
Because ThreadPoolExecutor is part of Standard Java I cannot (easily) set breakpoints to try and find out what it is doing, this is ThreadPoolExecutor code (standard Jave not my code)
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// 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();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
We experimented with the queue size in the Executor, by default it was 100 because I did not want it to get too large as the queue tasks will use more memory and I would rather the calling tasks just runs itself if queue is busy. But in an attempt solve the issue (and remove need for CallerRunPolicy to be called because queue full) I increased queue size to 1000 and this caused the error to occur more quickly and then removed the limit completely and continue to fail more rapidly
new LinkedBlockingQueue<Runnable>(BOUNDED_QUEUE_SIZE),
I was looking at an alternative to ThreadExecutorPool and came across ForkJoinPool - https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJoinPool.html
One thing I noticed is that ForkJoinPool has different methods for submitting tasks from within a task submitted to ForkJoinPool compared to submitting form outside. I dont why this is, but wondering if because I am submitting tasks from within tasks being run by Executor whther this could cause issue in some way ?
I have now managed to create own version of ThreadPoolExecutor by simply copying/pasting code into new Class, renaming, and also having to create a version of RejectedExcecutionhandler that expects my class rather than ThreadPoolExecutor and got this running.
Started to add some debugging to see if I can decipher what is going on, any ideas ?
Befotre call to processWorkerExit I added
MainWindow.userInfoLogger.severe("-----------------------"+getTaskCount()
+":"+getActiveCount()
+":"+w.completedTasks
+":"+ completedAbruptly);
and got on failure
-----------------------3686:0:593:false

For a long time I thought the problem must be with my code, I then started thinking the issue was with ThreadPoolExecutor, but adding debugging to my own version of runWorker() showed the problem was indeed my own code.
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
MainWindow.userInfoLogger.severe("-----------------------"+workQueue.size());
From this I could see that whilst the worker queue was getting generally longer and matched the value of
MainThreadAnalyzer.pendingItems -noOfWorkerThreads
at a particular point the two values diverged, and this was when the SongLoader process (which mistakenly I had not really considered) finished. So MainThreadAnalyzer was continuing to submit work increasing the value of pendingItems , but the work queue size of the Executor was getting smaller.
This lead to realization that the Executor had shutdown() alot earlier, but we hadn't realized this because only check latch after songloader had closed.
And the reason it had shutdown was because early on the MainAnalyzerThread was completing the work more quickly then SongLoader was submitting it so the value of pendingItems was temporarily set to zero allowing the latch to be closed.
The solution is as follows
Add a boolean flag to indicate when songLoader has completed and only allow latch to be closed once this flag is set.
private boolean songLoaderCompleted = false;
public void workDone(Callable task)
{
int remainingItems = pendingItems.decrementAndGet();
MainWindow.logger.severe(">>WorkDone:" + task.getClass().getName() + ":" +remainingItems);
if (remainingItems == 0 && songLoaderCompleted)
{
MainWindow.logger.severe(">Closing Latch:");
latch.countDown();
}
}
Then in main thread set this flag once SongLoader has completed
//Start SongLoader
ExecutorService songLoaderService = SongLoader.getExecutorService();
songLoaderService.submit(loader);
//SongLoader uses CompletionService when calls LoadFolderWorkers so shutdown wont return until all folder
//submissions completed to the MainAnalyserService
songLoaderService.shutdown();
songLoaderService.awaitTermination(10, TimeUnit.DAYS);
MainWindow.userInfoLogger.severe(">Song Loader Finished");
//Were now allowed to consider closing the latch because we know all songs have now been loaded
//so no false chance of zeroes
analyserService.setSongLoaderCompleted();
//Just waits for all the async tasks on the list to complete/fail
analyserService.awaitCompletion();
MainWindow.userInfoLogger.severe(">MainAnalyser Completed");
//This should be immediate as there should be no tasks still remaining
analyserService.getExecutorService().shutdown();
analyserService.getExecutorService().awaitTermination(10, TimeUnit.DAYS);

You are just misusing ExecutorService.
What you are doing (even in your "solution") is this
Submit tasks
Wait for them to finish
Shutdown
Wait again for shutdown to happen (why is that actually?)
What you should do is:
Submit tasks
Shutdown the executor to not allow any new tasks
Await termination - this will block until all tasks are finished, or timeout is reached
You should check for return status of awaitTermination because
If true - all tasks are finished before given timeout
If false - not all tasks are finished yet - and probably you should not start your second pool in such case.
Also there are 2 options how to use thread executor. You can spawn worker threads and let them decide what they supposed to do - like you did by looping in worker thread for new tasks
Or (which I prefer), wrap whatever is your job supposed to do into separate task (most probably what you have in loop body) and submit as separate task to pool. ExecutorService will do the scheduling for you.

Related

Check for thread shutdown and execute a task once it shutdown

I am creating a fixed-size thread pool with 10 threads as follows:
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < poolSize; ++i) {
executorService.execute(factory.get());
}
Now, after spawning 10 threads, a runnable is being executed by each of them. Runnable here is provided by factory.get()
Now, I wanted to do a thing that as soon as a thread gets shutdown, i.e. it has completed a task, it picks another runnable again and start running it. So, basically check for all 10 threads state and execute a runnable again if the thread is shutdown.
I know I can do something like, in which I can call the executorService shutdown() method as follows to do that:
while (!executorService.isShutdown()) {
try {
executorService.execute(factory.get());
} catch (RejectedExecutionException e) {
if (!executorService.isShutdown())
log.warn("task submission rejected");
}
}
But in this approach, issue is that I am keep on calling the execute function which would increase LinkedBlockingQueue and won't serve my purpose.
If I can somehow check the Threads state, that would be good because then, it would avoid the overhead of going back to get more work from the executor service.
Please suggest how can I do that in code.
You can use a bounded executor. The following is code by Brian Goetz from jcip
/**
* BoundedExecutor
* <p/>
* Using a Semaphore to throttle task submission
*
* #author Brian Goetz and Tim Peierls
*/
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
}
}
}
Then just create and use it:
ExecutorService executorService = Executors.newFixedThreadPool(10);
BoundedExecutor boundedExecutor = new BoundedExecutor(executorService,10);
while (!executorService.isShutdown()) {
try {
boundedExecutor.submitTask(factory.get());
} catch (InterruptedException e) {
}
}
This way you will always have 10 threads running, new tasks will only be submitted after the old ones will complete and you can stop the execution by shutting down the executor.
Why use a thread pool if you're going to run 10 threads continually? Just start 10 threads yourself.
Why have a "controller" thread on top of the 10 worker threads? Just let each thread ask for the next task to execute.
The following assumes that factory.get() is thread-safe.
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (;;) {
Runnable r = factory.get(); // <-- must be thread-safe
if (r == null)
break; // stop thread if no more tasks to execute
try {
r.run();
} catch (Exception e) {
// log exception here
}
}
}).start();
}
If needed, save the 10 thread objects in an array.
If you want to be able to shutdown the threads without having factory.get() returning null, add a volatile boolean, and check it in the loop.

Thread sleeping in a Thread-Pool

Let's say we have a thread-pool with a limited number of threads.
Executor executor = Executors.newFixedThreadPool(3);
Now let's say one of the active tasks must sleep for 3 seconds (for whatever reason).
executor.execute(() -> {
try {
Thread.sleep(3000L);
} catch (InterruptedException ignore) {}
});
How can we implement such a thread-pool in way that, when a task sleeps (or waits on a monitor/condition), the thread1 can be used effectively to run another task?
1 By thread I do not mean the "physical" Java thread, because that would be impossible while the thread is asleep. What I mean is, the thread-pool to have an abstract implementation which virtually seems to allow a thread to run another task during sleeping. The key point is that there are always N simultaneously running (non-sleeping) tasks.
Somewhat similar to the way a monitor handles access to a critical region:
If a thread waits on a resource, the resource can be used by another thread.
If the thread is notified, it is placed into the waiting set to (re-)gain access to that resource.
What you are asking for is essentially implementing coroutines/fibers on top of JVM/OS thread. Nice talk was given by Sanhong Li about the way how Alibaba's engineers implemented such construction - the idea is instead of relying on OS thread scheduler you need to rely on your own Selector.
See also Loom project for fibers (user-land green threads).
I implemented a minimal working example which basically does what I think you want.
A Task interface (much like the runnable interface, just with a passed Context to perform waiting)
package io.medev.stackoverflow;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
public interface Task {
/**
* Wraps the given runnable into a Task with a not guessable execution time (meaning guessExecutionTime always returns Long.MAX_VALUE)
* #param runnable The runnable to wrap
* #return a Task wrapping this runnable
*/
static Task wrap(Runnable runnable) {
return wrap(runnable, Long.MAX_VALUE);
}
/**
* Wraps the given runnable using the given guessedExecutionTimeMillis
* #param runnable The runnable to wrap
* #param guessedExecutionTimeMillis The guessed execution time in millis for this runnable
* #return a Task wrapping this runnable
*/
static Task wrap(Runnable runnable, long guessedExecutionTimeMillis) {
return new Task() {
#Override
public long guessExecutionTimeMillis() {
return guessedExecutionTimeMillis;
}
#Override
public void run(Context context) {
runnable.run();
}
};
}
/**
* Should more or less guess how long this task will run
* #return The execution time of this Task in milliseconds
*/
long guessExecutionTimeMillis();
void run(Context context);
interface Context {
/**
* Block until the condition is met, giving other Tasks time to execute
* #param condition the condition to check
* #throws InterruptedException if the current thread is interrupted
*/
void idle(BooleanSupplier condition) throws InterruptedException;
/**
* Blocks at least for the given duration, giving other Tasks time to execute
* #param timeout
* #param timeUnit
* #throws InterruptedException if the current thread is interrupted
*/
void idle(long timeout, TimeUnit timeUnit) throws InterruptedException;
/**
* Blocks until the condition is met or the timeout expires, giving other Tasks time to execute
* #param condition the condition to check
* #param timeout
* #param timeUnit
* #throws InterruptedException if the current thread is interrupted
*/
void idle(BooleanSupplier condition, long timeout, TimeUnit timeUnit) throws InterruptedException;
}
}
And a basic fixed thread-pool Executor - but you have to depend on the concrete implementation here:
package io.medev.stackoverflow;
import java.util.Comparator;
import java.util.concurrent.*;
import java.util.function.BooleanSupplier;
public class TimeEfficientExecutor implements Executor {
private final BlockingQueue<Task> taskQueue;
private final CountDownLatch latch;
private volatile boolean alive;
public TimeEfficientExecutor(int threads) {
this.taskQueue = new PriorityBlockingQueue<>(10, Comparator.comparingLong(Task::guessExecutionTimeMillis));
this.latch = new CountDownLatch(threads);
this.alive = true;
for (int i = 0; i < threads; i++) {
Thread thread = new Thread(new TimeEfficientExecutorRunnable());
thread.start();
}
}
#Override
public void execute(Runnable runnable) {
execute(Task.wrap(runnable));
}
public void execute(Runnable runnable, long guessedExecutionTimeMillis) {
execute(Task.wrap(runnable, guessedExecutionTimeMillis));
}
public void execute(Task task) {
this.taskQueue.offer(task);
}
public void shutdown() {
this.alive = false;
}
public void awaitShutdown() throws InterruptedException {
this.latch.await();
}
public void awaitShutdown(long timeout, TimeUnit timeUnit) throws InterruptedException {
this.latch.await(timeout, timeUnit);
}
private class TimeEfficientExecutorRunnable implements Runnable {
#Override
public void run() {
try {
while (TimeEfficientExecutor.this.alive) {
Task task = TimeEfficientExecutor.this.taskQueue.poll();
if (task != null) {
try {
task.run(new IdleTaskContext());
} catch (Exception e) {
// TODO: logging
}
}
}
} finally {
TimeEfficientExecutor.this.latch.countDown();
}
}
}
private class IdleTaskContext implements Task.Context {
#Override
public void idle(BooleanSupplier condition) throws InterruptedException {
idle(condition, Long.MAX_VALUE);
}
#Override
public void idle(long timeout, TimeUnit timeUnit) throws InterruptedException {
idle(() -> false, timeout, timeUnit);
}
#Override
public void idle(BooleanSupplier condition, long timeout, TimeUnit timeUnit) throws InterruptedException {
idle(condition, System.currentTimeMillis() + timeUnit.toMillis(timeout));
}
private void idle(BooleanSupplier condition, long idleUntilTs) throws InterruptedException {
long leftMillis = idleUntilTs - System.currentTimeMillis();
while (TimeEfficientExecutor.this.alive && !condition.getAsBoolean() && leftMillis >= 1L) {
Task task = TimeEfficientExecutor.this.taskQueue.poll(leftMillis, TimeUnit.MILLISECONDS);
leftMillis = idleUntilTs - System.currentTimeMillis();
if (task != null) {
if (leftMillis >= 1L && task.guessExecutionTimeMillis() < leftMillis) {
task.run(new IdleTaskContext());
} else {
TimeEfficientExecutor.this.taskQueue.offer(task);
}
}
}
}
}
}
Note that you can't just step down the stack - and the stack is bound to the executing thread. That means that it is not possible to jump back into an underlying idleing task if some "Sub"-Task starts idleing. You have to "trust" what each task returns in the guessExecutionTimeMillis-Method.
Thanks to the PriorityQueue used in the Executor, the queue will always return the task with the lowest exeuction time.

How to end a thread in executor service if thread takes too long?

Sample executor service
static class MyRunnable implements Runnable {
private String serverName;
public MyRunnable(String serverName) {
super();
this.serverName = serverName;
}
#Override
public void run() {
...
conn = new ch.ethz.ssh2.Connection(serverName);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
logger.info("Connecting to " + server);
if (isAuthenticated == false) {
logger.info(server + " Please check credentials");
}
sess = conn.openSession();
...
}
}
public static void main(String[] args) {
List<String> serverList = ...;
ExecutorService executor = Executors.newFixedThreadPool(20);
for (String serverName : serverList) {
MyRunnable r = new MyRunnable(serverName);
executor.execute(r);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
}
Right here is a sample code of my executor service. But with this logic when I meet a server that fails to connect or takes too long to connect it creates a a hang time within my application. I want to end/kill the thread if it takes longer than x amount of time to connect. How can I terminate the thread task if it does not connect to server within 2 seconds.
Attempt
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 25, 500, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1));
I added the following code but apparently it does not end the thread if it takes longer than 2000 milliseconds.
Attempt 2
Future<?> future = executor.submit( new task));
try {
future.get(2000, TimeUnit.MILLISECONDS); // This waits timeout seconds; returns null
}
catch(TimeoutException e) {
future.cancel(true);
// System.out.println(server + "name");
}
How can I terminate the thread task if it does not connect to server within 2 seconds.
This is difficult thing to do typically because even if you interrupt the thread (like the other answers mention) there's no guarantee that the thread will stop. Interrupt just sets a flag on the thread and it's up to the code to detect the status and stop. This means that a ton of threads may be in the background waiting for the connects.
In your case however you are using the ch.ethz.ssh2.Connection.connect() method. Turns out there is a connect method that takes a timeout. I think you want the following:
// try to connect for 2 seconds
conn.connect(null, 2000, 0);
To quote from the connect method javadocs:
In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.
You have to do awaitTermination() first, then check the return value, and then do shutdownNow(). shutdown() does not guarantee instant stoppage of the service, it just stops taking new jobs, and waits for all jobs to complete in order. shutdownNow() on the other hand, stops taking new jobs, actively attempts to stop all running tasks, and does not start any new one, returning a list of all waiting-to-execute jobs.
From JavaDocs :
The following method shuts down an ExecutorService in two phases,
first by calling shutdown to reject incoming tasks, and then calling
shutdownNow, if necessary, to cancel any lingering tasks:
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();
}
}
You can always call future.get(timeout...)
It will return timeout exception if it did not finish yet... then you can call future.cancel().
As long as you deal with threads in Java the only safe way to stop the thread is to interrupt it. You can call shutdown() first and then wait. This method doesn't interrupt threads.
If it doesn't help then you call shutdownNow() which tries to cancel tasks by setting interrupted flag of each thread to true. In that case if threads are blocked/waiting then InterruptedException will be thrown. If you check interrupted flag somewhere inside your tasks then you are good too.
But if you have no other choice but to stop threads you still can do it. One possible solution of getting access to workers is to trace all created threads inside ThreadPoolExecutor with help of custom thread factory.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class TestThreadPoolEx {
static class CustomThreadFactory implements ThreadFactory {
private List<Thread> threads = new ArrayList<>();
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
threads.add(t);
return t;
}
public List<Thread> getThreads() {
return threads;
}
public void stopThreads() {
for(Thread t : threads) {
if(t.isAlive()) {
try {
t.stop();
} catch (Exception e) {
//NOP
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
CustomThreadFactory factory = new CustomThreadFactory();
ExecutorService ex = Executors.newFixedThreadPool(1, factory);
ex.submit(() -> {
while(true);
});
ex.shutdown();
ex.awaitTermination(5, TimeUnit.SECONDS);
ex.shutdownNow();
ex.awaitTermination(5, TimeUnit.SECONDS);
factory.stopThreads();
}
}
This is sure unsafe but should fit your requirements. In this case it's able to stop while(true) loop. Cancelling tasks won't be able to do that.

Regarding creating synchronization mechanism [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Testing a multithreaded Java class that runs the threads sequentially
Please don't treat this below question as a duplicate one..!
I have developed a class that lets multi-threads to run sequentially, one at a time and in order. All the application code between this class' claimAccess function and release Access function will be executed only in one thread at one time. All other threads will wait in the queue until the previous thread completed.Please advise I want to test my class by writing a piece of code in main() method itself .
import java.util.ArrayList;
import java.util.List;
public class AccessGate {
protected boolean shouldWait = false;
protected final List waitThreadQueue = new ArrayList();
/**
* For a thread to determine if it should wait. It it is, the thread will
* wait until notified.
*
*/
public void claimAccess() {
final Thread thread = getWaitThread();
if (thread != null) {
// let the thread wait untill notified
synchronized (thread) {
try {
thread.wait();
} catch (InterruptedException exp) {
}
}
}
}
/**
* For a thread to determine if it should wait. It it is, the thread will be
* put into the waitThreadQueue to wait.
*
*/
private synchronized Thread getWaitThread() {
Thread thread = null;
if (shouldWait || !waitThreadQueue.isEmpty()) {
thread = Thread.currentThread();
waitThreadQueue.add(thread);
}
shouldWait = true;
return thread;
}
/**
* Release the thread in the first position of the waitThreadQueue.
*
*/
public synchronized void releaseAccess() {
if (waitThreadQueue.isEmpty()) {
shouldWait = false;
} else {
shouldWait = true;
// give the claimAccess function a little time to complete
try {
Thread.sleep(10);
} catch (InterruptedException exp) {
}
// release the waiting thread
final Thread thread = (Thread) waitThreadQueue.remove(0);
synchronized (thread) {
thread.notifyAll();
}
}
}
}
Now my main method would be ..
public static void main (String args[])
{
}
please advise how I spawn thr threads in my my main method to test the above class..!!Please advise
This should get you started...
public static void main (String args[])
{
AccessGate gate = new AccessGate();
// create as many threads as you like
Thread t1 = new MyThread(gate);
Thread t2 = new MyThread(gate);
// start all the threads you created
t1.start();
t2.start();
}
class MyThread extends Thread {
AccessGate gate;
public MyThread(AccessGate g) {
gate = g;
}
public void run() {
gate.claimAccess();
// Do something or print something.
// Could output several statements.
// Why not do a sleep as well to see if other threads interrupt
// this code section.
gate.releaseAccess();
}
}
Consider using Executors.newSingleThreadExecutor(). This is a thread pool with only one thread executing tasks. Next task will start execution only after first task is finished:
Executor executor = Executors.newSingleThreadExecutor();
Future<String> future1 = executor.submit(new Callable<String>() {
#Override
String call() throws Exception {
// my first task
}
});
Future<String> future2 = executor.submit(new Callable<String>() {
#Override
String call() throws Exception {
// my second task
}
});
...
You can retrieve result of task execution via Future API, also it allows you to track status of each job.

How to timeout a thread

I want to run a thread for some fixed amount of time. If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How can it be done?
One way of doing it as I figured out from this thread
is to use a TimerTask inside the run() method of the Thread.
Are there any better solutions for this?
EDIT: Adding a bounty as I needed a clearer answer. The ExecutorService code given below does not address my problem. Why should I sleep() after executing (some code - I have no handle over this piece of code)? If the code is completed and the sleep() is interrupted, how can that be a timeOut?
The task that needs to be executed is not in my control. It can be any piece of code. The problem is this piece of code might run into an infinite loop. I don't want that to happen. So, I just want to run that task in a separate thread. The parent thread has to wait till that thread finishes and needs to know the status of the task (i.e whether it timed out or some exception occured or if its a success). If the task goes into an infinite loop, my parent thread keeps on waiting indefinitely, which is not an ideal situation.
Indeed rather use ExecutorService instead of Timer, here's an SSCCE:
package com.stackoverflow.q2275443;
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!";
}
}
Play a bit with the timeout argument in Future#get() method, e.g. increase it to 5 and you'll see that the thread finishes. You can intercept the timeout in the catch (TimeoutException e) block.
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep(). Inside your long running task, you should be checking if the thread is not interrupted as follows:
while (!Thread.interrupted()) {
// Do your long running task here.
}
There isn't a 100% reliable way to do this for any old task. The task has to be written with this ability in mind.
Core Java libraries like ExecutorService cancel asynchronous tasks with interrupt() calls on the worker thread. So, for example, if the task contains some sort of loop, you should be checking its interrupt status on each iteration. If the task is doing I/O operations, they should be interruptible too—and setting that up can be tricky. In any case, keep in mind that code has to actively check for interrupts; setting an interrupt doesn't necessarily do anything.
Of course, if your task is some simple loop, you can just check the current time at each iteration and give up when a specified timeout has elapsed. A worker thread isn't needed in that case.
Consider using an instance of ExecutorService. Both invokeAll() and invokeAny() methods are available with a timeout parameter.
The current thread will block until the method completes (not sure if this is desirable) either because the task(s) completed normally or the timeout was reached. You can inspect the returned Future(s) to determine what happened.
Assuming the thread code is out of your control:
From the Java documentation mentioned above:
What if a thread doesn't respond to Thread.interrupt?
In some cases, you can use application specific tricks. For example,
if a thread is waiting on a known socket, you can close the socket to
cause the thread to return immediately. Unfortunately, there really
isn't any technique that works in general. It should be noted that in
all situations where a waiting thread doesn't respond to
Thread.interrupt, it wouldn't respond to Thread.stop either. Such
cases include deliberate denial-of-service attacks, and I/O operations
for which thread.stop and thread.interrupt do not work properly.
Bottom Line:
Make sure all threads can be interrupted, or else you need specific knowledge of the thread - like having a flag to set. Maybe you can require that the task be given to you along with the code needed to stop it - define an interface with a stop() method. You can also warn when you failed to stop a task.
BalusC said:
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep().
But if you replace Thread.sleep(4000); with for (int i = 0; i < 5E8; i++) {} then it doesn't compile, because the empty loop doesn't throw an InterruptedException.
And for the thread to be interruptible, it needs to throw an InterruptedException.
This seems like a serious problem to me. I can't see how to adapt this answer to work with a general long-running task.
Edited to add: I reasked this as a new question: [ interrupting a thread after fixed time, does it have to throw InterruptedException? ]
I created a helper class just for this some time ago. Works great:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* TimeOut class - used for stopping a thread that is taking too long
* #author Peter Goransson
*
*/
public class TimeOut {
Thread interrupter;
Thread target;
long timeout;
boolean success;
boolean forceStop;
CyclicBarrier barrier;
/**
*
* #param target The Runnable target to be executed
* #param timeout The time in milliseconds before target will be interrupted or stopped
* #param forceStop If true, will Thread.stop() this target instead of just interrupt()
*/
public TimeOut(Runnable target, long timeout, boolean forceStop) {
this.timeout = timeout;
this.forceStop = forceStop;
this.target = new Thread(target);
this.interrupter = new Thread(new Interrupter());
barrier = new CyclicBarrier(2); // There will always be just 2 threads waiting on this barrier
}
public boolean execute() throws InterruptedException {
// Start target and interrupter
target.start();
interrupter.start();
// Wait for target to finish or be interrupted by interrupter
target.join();
interrupter.interrupt(); // stop the interrupter
try {
barrier.await(); // Need to wait on this barrier to make sure status is set
} catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
return success; // status is set in the Interrupter inner class
}
private class Interrupter implements Runnable {
Interrupter() {}
public void run() {
try {
Thread.sleep(timeout); // Wait for timeout period and then kill this target
if (forceStop) {
target.stop(); // Need to use stop instead of interrupt since we're trying to kill this thread
}
else {
target.interrupt(); // Gracefully interrupt the waiting thread
}
System.out.println("done");
success = false;
} catch (InterruptedException e) {
success = true;
}
try {
barrier.await(); // Need to wait on this barrier
} catch (InterruptedException e) {
// If the Child and Interrupter finish at the exact same millisecond we'll get here
// In this weird case assume it failed
success = false;
}
catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
}
}
}
It is called like this:
long timeout = 10000; // number of milliseconds before timeout
TimeOut t = new TimeOut(new PhotoProcessor(filePath, params), timeout, true);
try {
boolean sucess = t.execute(); // Will return false if this times out
if (!sucess) {
// This thread timed out
}
else {
// This thread ran completely and did not timeout
}
} catch (InterruptedException e) {}
I think you should take a look at proper concurrency handling mechanisms (threads running into infinite loops doesn't sound good per se, btw). Make sure you read a little about the "killing" or "stopping" Threads topic.
What you are describing,sound very much like a "rendezvous", so you may want to take a look at the CyclicBarrier.
There may be other constructs (like using CountDownLatch for example) that can resolve your problem (one thread waiting with a timeout for the latch, the other should count down the latch if it has done it's work, which would release your first thread either after a timeout or when the latch countdown is invoked).
I usually recommend two books in this area: Concurrent Programming in Java and Java Concurrency in Practice.
In the solution given by BalusC, the main thread will stay blocked for the timeout period. If you have a thread pool with more than one thread, you will need the same number of additional thread that will be using Future.get(long timeout,TimeUnit unit) blocking call to wait and close the thread if it exceeds the timeout period.
A generic solution to this problem is to create a ThreadPoolExecutor Decorator that can add the timeout functionality. This Decorator class should create as many threads as ThreadPoolExecutor has, and all these threads should be used only to wait and close the ThreadPoolExecutor.
The generic class should be implemented like below:
import java.util.List;
import java.util.concurrent.*;
public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor {
private final ThreadPoolExecutor commandThreadpool;
private final long timeout;
private final TimeUnit unit;
public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool,
long timeout,
TimeUnit unit ){
super( threadpool.getCorePoolSize(),
threadpool.getMaximumPoolSize(),
threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS),
TimeUnit.MILLISECONDS,
threadpool.getQueue());
this.commandThreadpool = threadpool;
this.timeout=timeout;
this.unit=unit;
}
#Override
public void execute(Runnable command) {
super.execute(() -> {
Future<?> future = commandThreadpool.submit(command);
try {
future.get(timeout, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException e) {
throw new RejectedExecutionException(e);
} finally {
future.cancel(true);
}
});
}
#Override
public void setCorePoolSize(int corePoolSize) {
super.setCorePoolSize(corePoolSize);
commandThreadpool.setCorePoolSize(corePoolSize);
}
#Override
public void setThreadFactory(ThreadFactory threadFactory) {
super.setThreadFactory(threadFactory);
commandThreadpool.setThreadFactory(threadFactory);
}
#Override
public void setMaximumPoolSize(int maximumPoolSize) {
super.setMaximumPoolSize(maximumPoolSize);
commandThreadpool.setMaximumPoolSize(maximumPoolSize);
}
#Override
public void setKeepAliveTime(long time, TimeUnit unit) {
super.setKeepAliveTime(time, unit);
commandThreadpool.setKeepAliveTime(time, unit);
}
#Override
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
super.setRejectedExecutionHandler(handler);
commandThreadpool.setRejectedExecutionHandler(handler);
}
#Override
public List<Runnable> shutdownNow() {
List<Runnable> taskList = super.shutdownNow();
taskList.addAll(commandThreadpool.shutdownNow());
return taskList;
}
#Override
public void shutdown() {
super.shutdown();
commandThreadpool.shutdown();
}
}
The above decorator can be used as below:
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
long timeout = 2000;
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true));
threadPool = new TimeoutThreadPoolDecorator( threadPool ,
timeout,
TimeUnit.MILLISECONDS);
threadPool.execute(command(1000));
threadPool.execute(command(1500));
threadPool.execute(command(2100));
threadPool.execute(command(2001));
while(threadPool.getActiveCount()>0);
threadPool.shutdown();
}
private static Runnable command(int i) {
return () -> {
System.out.println("Running Thread:"+Thread.currentThread().getName());
System.out.println("Starting command with sleep:"+i);
try {
Thread.sleep(i);
} catch (InterruptedException e) {
System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!");
return;
}
System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i);
};
}
}
I post you a piece of code which show a way how to solve the problem.
As exemple I'm reading a file.
You could use this method for another operation, but you need to implements the kill() method so that the main operation will be interrupted.
hope it helps
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Main class
*
* #author el
*
*/
public class Main {
/**
* Thread which perform the task which should be timed out.
*
* #author el
*
*/
public static class MainThread extends Thread {
/**
* For example reading a file. File to read.
*/
final private File fileToRead;
/**
* InputStream from the file.
*/
final private InputStream myInputStream;
/**
* Thread for timeout.
*/
final private TimeOutThread timeOutThread;
/**
* true if the thread has not ended.
*/
boolean isRunning = true;
/**
* true if all tasks where done.
*/
boolean everythingDone = false;
/**
* if every thing could not be done, an {#link Exception} may have
* Happens.
*/
Throwable endedWithException = null;
/**
* Constructor.
*
* #param file
* #throws FileNotFoundException
*/
MainThread(File file) throws FileNotFoundException {
setDaemon(false);
fileToRead = file;
// open the file stream.
myInputStream = new FileInputStream(fileToRead);
// Instantiate the timeout thread.
timeOutThread = new TimeOutThread(10000, this);
}
/**
* Used by the {#link TimeOutThread}.
*/
public void kill() {
if (isRunning) {
isRunning = false;
if (myInputStream != null) {
try {
// close the stream, it may be the problem.
myInputStream.close();
} catch (IOException e) {
// Not interesting
System.out.println(e.toString());
}
}
synchronized (this) {
notify();
}
}
}
/**
* The task which should be timed out.
*/
#Override
public void run() {
timeOutThread.start();
int bytes = 0;
try {
// do something
while (myInputStream.read() >= 0) {
// may block the thread.
myInputStream.read();
bytes++;
// simulate a slow stream.
synchronized (this) {
wait(10);
}
}
everythingDone = true;
} catch (IOException e) {
endedWithException = e;
} catch (InterruptedException e) {
endedWithException = e;
} finally {
timeOutThread.kill();
System.out.println("-->read " + bytes + " bytes.");
isRunning = false;
synchronized (this) {
notifyAll();
}
}
}
}
/**
* Timeout Thread. Kill the main task if necessary.
*
* #author el
*
*/
public static class TimeOutThread extends Thread {
final long timeout;
final MainThread controlledObj;
TimeOutThread(long timeout, MainThread controlledObj) {
setDaemon(true);
this.timeout = timeout;
this.controlledObj = controlledObj;
}
boolean isRunning = true;
/**
* If we done need the {#link TimeOutThread} thread, we may kill it.
*/
public void kill() {
isRunning = false;
synchronized (this) {
notify();
}
}
/**
*
*/
#Override
public void run() {
long deltaT = 0l;
try {
long start = System.currentTimeMillis();
while (isRunning && deltaT < timeout) {
synchronized (this) {
wait(Math.max(100, timeout - deltaT));
}
deltaT = System.currentTimeMillis() - start;
}
} catch (InterruptedException e) {
// If the thread is interrupted,
// you may not want to kill the main thread,
// but probably yes.
} finally {
isRunning = false;
}
controlledObj.kill();
}
}
/**
* Start the main task and wait for the end.
*
* #param args
* #throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
long start = System.currentTimeMillis();
MainThread main = new MainThread(new File(args[0]));
main.start();
try {
while (main.isRunning) {
synchronized (main) {
main.wait(1000);
}
}
long stop = System.currentTimeMillis();
if (main.everythingDone)
System.out.println("all done in " + (stop - start) + " ms.");
else {
System.out.println("could not do everything in "
+ (stop - start) + " ms.");
if (main.endedWithException != null)
main.endedWithException.printStackTrace();
}
} catch (InterruptedException e) {
System.out.println("You've killed me!");
}
}
}
Regards
Here is my really simple to use helper class to run or call piece of Java code :-)
This is based on the excellent answer from BalusC
package com.mycompany.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
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;
/**
* Calling {#link Callable#call()} or Running {#link Runnable#run()} code
* with a timeout based on {#link Future#get(long, TimeUnit))}
* #author pascaldalfarra
*
*/
public class CallableHelper
{
private CallableHelper()
{
}
public static final void run(final Runnable runnable, int timeoutInSeconds)
{
run(runnable, null, timeoutInSeconds);
}
public static final void run(final Runnable runnable, Runnable timeoutCallback, int timeoutInSeconds)
{
call(new Callable<Void>()
{
#Override
public Void call() throws Exception
{
runnable.run();
return null;
}
}, timeoutCallback, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, int timeoutInSeconds)
{
return call(callable, null, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, Runnable timeoutCallback, int timeoutInSeconds)
{
ExecutorService executor = Executors.newSingleThreadExecutor();
try
{
Future<T> future = executor.submit(callable);
T result = future.get(timeoutInSeconds, TimeUnit.SECONDS);
System.out.println("CallableHelper - Finished!");
return result;
}
catch (TimeoutException e)
{
System.out.println("CallableHelper - TimeoutException!");
if(timeoutCallback != null)
{
timeoutCallback.run();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
finally
{
executor.shutdownNow();
executor = null;
}
return null;
}
}
The following snippet will start an operation in a separate thread, then wait for up to 10 seconds for the operation to complete. If the operation does not complete in time, the code will attempt to cancel the operation, then continue on its merry way. Even if the operation cannot be cancelled easily, the parent thread will not wait for the child thread to terminate.
ExecutorService executorService = getExecutorService();
Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() {
public SomeClass call() {
// Perform long-running task, return result. The code should check
// interrupt status regularly, to facilitate cancellation.
}
});
try {
// Real life code should define the timeout as a constant or
// retrieve it from configuration
SomeClass result = future.get(10, TimeUnit.SECONDS);
// Do something with the result
} catch (TimeoutException e) {
future.cancel(true);
// Perform other error handling, e.g. logging, throwing an exception
}
The getExecutorService() method can be implemented in a number of ways. If you do not have any particular requirements, you can simply call Executors.newCachedThreadPool() for thread pooling with no upper limit on the number of threads.
One thing that I've not seen mentioned is that killing threads is generally a Bad Idea. There are techniques for making threaded methods cleanly abortable, but that's different to just killing a thread after a timeout.
The risk with what you're suggesting is that you probably don't know what state the thread will be in when you kill it - so you risk introducing instability. A better solution is to make sure your threaded code either doesn't hang itself, or will respond nicely to an abort request.
Great answer by BalusC's:
but Just to add that the timeout itself does not interrupt the thread itself. even if you are checking with while(!Thread.interrupted()) in your task. if you want to make sure thread is stopped you should also make sure future.cancel() is invoked when timeout exception is catch.
package com.stackoverflow.q2275443;
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) {
//Without the below cancel the thread will continue to live
// even though the timeout exception thrown.
future.cancel();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
while(!Thread.currentThread.isInterrupted()){
System.out.println("Im still running baby!!");
}
}
}
I think the answer mainly depends on the task itself.
Is it doing one task over and over again?
Is it necessary that the timeout interrupts a currently running task immediately after it expires?
If the first answer is yes and the second is no, you could keep it as simple as this:
public class Main {
private static final class TimeoutTask extends Thread {
private final long _timeoutMs;
private Runnable _runnable;
private TimeoutTask(long timeoutMs, Runnable runnable) {
_timeoutMs = timeoutMs;
_runnable = runnable;
}
#Override
public void run() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() < (start + _timeoutMs)) {
_runnable.run();
}
System.out.println("execution took " + (System.currentTimeMillis() - start) +" ms");
}
}
public static void main(String[] args) throws Exception {
new TimeoutTask(2000L, new Runnable() {
#Override
public void run() {
System.out.println("doing something ...");
try {
// pretend it's taking somewhat longer than it really does
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
If this isn't an option, please narrow your requirements - or show some code.
I was looking for an ExecutorService that can interrupt all timed out Runnables executed by it, but found none. After a few hours I created one as below. This class can be modified to enhance robustness.
public class TimedExecutorService extends ThreadPoolExecutor {
long timeout;
public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) {
super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(numThreads + 1));
this.timeout = unit.toMillis(timeout);
}
#Override
protected void beforeExecute(Thread thread, Runnable runnable) {
Thread interruptionThread = new Thread(new Runnable() {
#Override
public void run() {
try {
// Wait until timeout and interrupt this thread
Thread.sleep(timeout);
System.out.println("The runnable times out.");
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
interruptionThread.start();
}
}
Usage:
public static void main(String[] args) {
Runnable abcdRunnable = new Runnable() {
#Override
public void run() {
System.out.println("abcdRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("abcdRunnable ended");
}
};
Runnable xyzwRunnable = new Runnable() {
#Override
public void run() {
System.out.println("xyzwRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("xyzwRunnable ended");
}
};
int numThreads = 2, timeout = 5;
ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS);
timedExecutor.execute(abcdRunnable);
timedExecutor.execute(xyzwRunnable);
timedExecutor.shutdown();
}
Now , l meet a issue like this. It happens to decode picture. The process of decode takes too much time that the screen keep black. l add a time controler: when the time is too long, then pop up from the current Thread.
The following is the diff:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Bitmap> future = executor.submit(new Callable<Bitmap>() {
#Override
public Bitmap call() throws Exception {
Bitmap bitmap = decodeAndScaleBitmapFromStream(context, inputUri);// do some time consuming operation
return null;
}
});
try {
Bitmap result = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e){
future.cancel(true);
}
executor.shutdown();
return (bitmap!= null);
I had the same problem. So i came up with a simple solution like this.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* #return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* #param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
Guarantees that if block didn't execute within the time limit. the process will terminate and throws an exception.
example :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
#Override
public void run() {
//TO DO write block of code
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}

Categories

Resources