Is there a way to kill a child thread after some specified time limit in Java?
Edit: Also this particular thread may be blocked in its worst case (Thread is used to wait for a file modification and blocks until this event occurs), so im not sure that interrupt() will be successful?
Make use of ExecutorService to execute the Callable, checkout the methods wherein you can specify the timeout. E.g.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Here Task of course implements Callable.
Some helpful changes were introduced as part of JEP 266 in CompletableFuture since Java 9. Using orTimeout method, for now, it is possible to write it like:
CompletableFuture.runAsync(thread::run)
.orTimeout(30, TimeUnit.SECONDS)
.exceptionally(throwable -> {
log.error("An error occurred", throwable);
return null;
});
In Java 8, unfortunately, you should use some extra code. Here is an example of delegation pattern usage with help of Lombok:
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.TimeoutException;
import static lombok.AccessLevel.PRIVATE;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
#AllArgsConstructor(access = PRIVATE)
public class TimeoutableCompletableFuture<T> extends CompletableFuture<T> {
public static TimeoutableCompletableFuture<Void> runAsync(
Runnable runnable) {
return new TimeoutableCompletableFuture<>(
CompletableFuture.runAsync(runnable));
}
#Delegate
private final CompletableFuture<T> baseFuture;
public TimeoutableCompletableFuture<T> orTimeout(Duration duration) {
final CompletableFuture<T> otherFuture = new CompletableFuture<>();
Executors.newScheduledThreadPool(
1,
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("timeoutable-%d")
.build())
.schedule(() -> {
TimeoutException ex = new TimeoutException(
"Timeout after " + duration);
return otherFuture.completeExceptionally(ex);
}, duration.toMillis(), MILLISECONDS);
return new TimeoutableCompletableFuture<>(
baseFuture.applyToEither(otherFuture, a -> a));
}
}
Of course, the code above easily could be rewritten as just a static factory method:
public static CompletableFuture<Void> runAsyncOrTimeout(
Runnable runnable, long timeout, TimeUnit unit) {
CompletableFuture<Void> other = new CompletableFuture<>();
Executors.newScheduledThreadPool(
1,
new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("timeoutafter-%d")
.build())
.schedule(() -> {
TimeoutException ex = new TimeoutException(
"Timeout after " + timeout);
return other.completeExceptionally(ex);
}, timeout, unit);
return CompletableFuture.runAsync(runnable).applyToEither(other, a -> a);
}
Not directly; I think the simplest way is to join() on that thread with that time limit, and interrupt the thread if it's not done by the time the join ended.
So,
Thread t = ...
t.join(timelimit);
if (t.isAlive()) t.interrupt();
Notice I used interrupt instead of actually killing it, it's much safer. I would also recommend using executors instead of directly manipulating threads.
Why not interrupt() it after a particular time ? Your spawned thread will have to be able to handle an InterruptedException properly.
See this article (http://www.javaspecialists.eu/archive/Issue056.html) for more information on shutting down threads cleanly.
See also the Executor/Future framework, which provide useful methods for collecting results and/or terminating threads within particular time limits.
You can use AOP and a #Timeable annotation for your method from jcabi-aspects (I'm a developer):
#Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
// do something time consuming
}
When time limit is reached your thread will get interrupted() flag set to true and it's your job to handle this situation correctly and to stop execution. Normally it's done by Thread.sleep(..).
Killing a thread is generally a bad idea for reasons linked to for the API docs for Thread.
If you are dead set on killing, use a whole new process.
Otherwise the usual thing is to have the thread poll System.nanoTime, poll a (possible volatile) flag, queue a "poison pill" or something of that nature.
Brian's right, interrupting it is safer than "stopping" the thread.
What if the thread is locking on an object mid-modification, and suddenly gets stopped (which causes the lock to be released)? You get weird results.
Do not use destroy() since that does not perform any cleanup.
The most straightforward way is to use join(), like
try {
thread.join();
} catch (InterruptedException e) {//log exception...}
You could use an ExecutorService. That would make a lot of sense if you have several threads running concurrently. If you have the need to spawn new threads while other threads are running, you can combine this with a BlockingQueue.
A ThreadPoolExecutor (an ExecutorService-implementation) can take a BlockingQueue as argument, and you can simply add new threads to the queue. When you are done you simply terminate the ThreadPoolExecutor.
private BlockingQueue<Runnable> queue;
...
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000),
TimeUnit.MILLISECONDS, this.queue);
You can keep a count of all the threads added to the queue. When you think you are done (the queue is empty, perhaps?) simply compare this to
if (issuedThreads == pool.getCompletedTaskCount()) {
pool.shutdown();
}
If the two match, you are done. Another way to terminate the pool is to wait a second in a loop:
try {
while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {//log exception...}
Related
In java, I have ExecutorService that runs with while true, and Throwable catch clouse. I find out that from time to time the thread goes down. That means the system stop function.
So my question is, first of all, how can I catch the "thread killed" event (in order to send me email on such case)?
Also, how can this thread goes down?
the code is:
ExecutorService changesTrackerThread = Executors.newSingleThreadExecutor();
changesTrackerThread.submit(queueUpdater());
private Runnable queueUpdater() {
return new Runnable() {
#Override
public void run() {
while (true)
{
try
{
// do some code, then sleep
Thread.sleep(2000L);
} catch (Throwable t)
{
_log.error("something bad happened, but the loop should keep running", t);
}
}
}
};
Well first of all, why are you using a while loop here!?
You should use a scheduled executor:
ExecutorService changesTrackerThread = Executors.newSingleThreadScheduledExecutor()();
changesTrackerThread.scheduleAtFixedRate(new queueUpdater(), 0, 2, TimeUnit.SECONDS);
private Runnable queueUpdater() {
return new Runnable() {
#Override
public void run() {
try
{
// do some code
} catch (Throwable t)
{
_log.error("something bad happened", t);
}
}
};
I do not know why your thread dies, show us the full code.
But this way even if the thread dies the Excecutor will rerun it after the given period(2 seconds in this example.
As others have noted, you could replace your while (true) and sleep() loop with a ScheduledExecutorService. Scheduling a repeating task on such a service will return a ScheduledFuture which you can use to check the status of this task or to cancel it if you have a need for that. This will enable you to remove the try/catch block from the code.
Start the service like this:
ScheduledExecutorService svc = Executors.newScheduledThreadPool(1);
I would use newScheduledThreadPool() instead of newSingleThreadScheduledExecutor() since the former will restart threads if necessary.
Then, schedule the work like this:
void doSomeCode() {
// do some code
}
ScheduledFuture<?> sf = svc.scheduleAtFixedRate(this::doSomeCode, 0L, 2L, TimeUnit.SECONDS);
(Or if you wish you can inline doSomeCode() as a lambda or an anonymous inner class.)
Now what happens if the task fails with an exception? The ScheduledFuture object returned allows you to check status in a variety of ways. If you have a thread that you can dedicate to waiting for failures, you can have it call sf.get() which will throw an ExecutionException that wraps the exception that caused the task to fail. Otherwise, it blocks indefinitely. ScheduledFuture.get() is a bit weird in that unlike an ordinary Future.get() call, it never returns a value; it always throws an exception.
When/if the task fails, the caller of sf.get() can log the exception and resubmit the task, or whatever. If you don't want to block a thread indefinitely, you can poll for failure using sf.isDone() or sf.get(0L, TimeUnit.SECONDS). Note that both overloads of sf.get() communicate all of their return information via the type of a thrown exception, which may make them somewhat inconvenient to use.
You could put exception handling within the task itself, catching Throwable and continuing no matter what, and this will probably work. It does bake the logging/restart/resubmission policy into the task itself, which may be unpleasant. Using ScheduledFuture lets you separate these policies from the actual work performed by the task.
I am writing code where I need to make sure that no threads are currently running in a thread pool before I commit results (to avoid losing data I should have put in the commit). For that, I'm using:
while (_executor.getActiveCount() > 0)
{
try
{
Thread.sleep(10); // milliseconds
}
catch (InterruptedException e)
{
// OK do nothing
}
}
But a colleague pointed out in review that the doc for getActiveCount states:
Returns the approximate number of threads that are actively
executing tasks.
So, is there a risk I would get out of the while loop while there are still active threads in the pool? If so, what would be the correct way to wait for all my worker threads to be done?
Edit: To give some more context: this is an online system, where the task that contains the executor service is left running indefinitely. Work comes in via a messaging system, is put on a thread in the executor, which doesn't need any synchronization, and works come out into another queue for the messaging system. I don't want to kill the executor to wait for completion of tasks.
You might want to consider using a CompletionService (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html).
A CompletionService wraps an ExecutorService and returns a Future when tasks are submitted. By maintaining a list of these Futures, you can see if the jobs that you're waiting on have completed. It also has the additional advantage that you can have others use the same ExecutorService since you have some means of accounting,
_executor.awaitTermination(); should do the job. Now, it won't actually wait for the threads to shutdown, but rather it would wait for all available tasks to terminate.
You could also provide keepAliveTime to a thread pool constructor to instantly terminate idle threads:
ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
To notify a thread that it should clean up and terminate, use the interrupt method.
t.interrupt();
and it is good to print or have log of your errors from catch block.
When tasks are submitted to the executor, they return Futures, which indicate when they complete. That is the preferred mechanism to use.
You can use JDK ExecutorService shutdown/awaitTermination.
Use case: need to cleanup thread-locals in pool threads upon their completion and this cleanup can take long (e.g. connection close). Only after that the main thread can continue.
A worker thread can register itself in some collection. For that override start() and run() and pass a custom thread factory to ThreadPoolExecutor:
class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(final Runnable r) {
return new MyThread(r);
}
...
class Some {
void waitAllThreads() {
Thread worker;
while ((worker = workerThreads.poll()) != null) {
worker.join();
}
}
...
class MyThread extends Thread {
#Override
public synchronized void start() {
if (getState() == State.NEW) {
some.workerThreads.offer(this);
}
super.start();
}
#Override
public void run() {
try {
super.run();
} finally {
some.workerThreads.remove(this);
}
}
...
I am getting data from a queue server and I need to process it and send an acknowledgement. Something like this:
while (true) {
queueserver.get.data
ThreadPoolExecutor //send data to thread
queueserver.acknowledgement
I don't fully understand what happens in threads but I think this program gets the data, sends it the thread and then immediately acknowledges it. So even if I have a limit of each queue can only have 200 unacknowledged items, it will just pull as fast as it can receive it. This is good when I write a program on a single server, but if I'm using multiple workers then this becomes an issue because the amount of items in the thread queue are not a reflection of the work its done but instead of how fast it can get items from the queue server.
Is there anything I can do to somehow make the program wait if the thread queue is full of work?
How can I make ThreadPoolExecutor command wait if there's too much data it needs to work on?
Instead of an open-ended queue, you can use a BlockingQueue with a limit on it:
BlockingQueue<Date> queue = new ArrayBlockingQueue<Date>(200);
In terms of jobs submitted to an ExecutorService, instead of using the default ExecutorServices created using Executors, which use an unbounded queue, you can create your own:
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(200));
Once the queue fills up, it will cause it to reject any new tasks that are submitted. You will need to set a RejectedExecutionHandler that submits to the queue. Something like:
final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, queue);
// by default (unfortunately) the ThreadPoolExecutor will throw an exception
// when you submit the 201st job, to have it block you do:
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// this will block if the queue is full
executor.getQueue().put(r);
// check afterwards and throw if pool shutdown
if (executor.isShutdown()) {
throw new RejectedExecutionException(
"Task " + r + " rejected from " + e);
}
}
});
I think it's a major miss that Java doesn't have a ThreadPoolExecutor.CallerBlocksPolicy.
If you want the acknowledgment when the worker starts working on the task, you can make a custom ThreadFactory that sends the acknowledgment from the thread before doing the actual work. OR you can override beforeExecute of a ThreadPoolExecutor.
If you want the acknowledgment when a new worker is freed up for a new task, I think you can initialize a ThreadPoolExecutor with a SynchronousQueue and a ThreadPoolExecutor.CallerRunsPolicy, or with your own policy where the caller blocks.
first, i think your attitude is wrong because what you did in your pseudo code is busy waiting, you should read through the Concurrency tutorial from java toturial http://docs.oracle.com/javase/tutorial/essential/concurrency/
ignoring that, ill offer you a solution with the busy wait (which is not recommanded):
ExecutorService e1 = Executors.newFixedThreadPool(20);
while (true) {
if (!serverq.isEmpty() && !myq.isFull()) myq.enq(serverq.poll());
if (!myq.isEmpty()) e1.execute(myq.poll());
}
NOTES:
1.make sure your myq is synchronized, as said in the other answers. you can extend some blocking queue to make sure the synchronization is correct.
2.you implement a runnable class which does what you exepct from the server in an iteration
of service, those runnables have to get myq as a parameter to the constructor and save it as global variable.
3.myq gets the runnables, that in the end of its run method, you must make sure the runnable deletes itself from myq.
What about having a blockingPool which will not execute more than 200 tasks and wait for a task to complete before submitting 201 task. I've achieved it using semaphore in my application. You can also change the limit by passing the value to its constructor.
Only difference here from #Gray answer is that rarely any task will get rejected in this case. Semaphore will make any 201 task to wait unless a other task gets over. Nevertheless, we have rejection handler to re-submit that task to executor in case of any rejection.
private class BlockingPool extends ThreadPoolExecutor {
private final Semaphore semaphore;
public BlockingPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, int tasksAllowedInThreads){
super(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
executor.execute(r);
}
});
semaphore = new Semaphore(tasksAllowedInThreads);
}
#Override
public void execute(Runnable task){
boolean acquired = false;
do{
try{
semaphore.acquire();
acquired = true;
} catch (final InterruptedException e){
// log
}
} while (!acquired); // run in loop to handle InterruptedException
try{
super.execute(task);
} catch (final RejectedExecutionException e){
System.out.println("Task Rejected");
semaphore.release();
throw e;
}
}
#Override
protected void afterExecute(Runnable r, Throwable t){
super.afterExecute(r, t);
if (t != null){
t.printStackTrace();
}
semaphore.release();
}
}
Does this make sense!
Encountered a situation when ThreadPoolExecutor is parked in execute(Runnable) function while all the ThreadPool threads are waiting in getTask func, workQueue is empty.
Does anybody have any ideas?
The ThreadPoolExecutor is created with ArrayBlockingQueue, and corePoolSize == maximumPoolSize = 4
[Edit] To be more precise, the thread is blocked in ThreadPoolExecutor.exec(Runnable command) func. It has the task to execute, but doesn't do it.
[Edit2] The executor is blocked somewhere inside the working queue (ArrayBlockingQueue).
[Edit3] The callstack:
thread = front_end(224)
at sun.misc.Unsafe.park(Native methord)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:778)
at
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1114)
at
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at java.util.concurrent.ArrayBlockingQueue.offer(ArrayBlockingQueue.java:224)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:653)
at net.listenThread.WorkersPool.execute(WorkersPool.java:45)
at the same time the workQueue is empty (checked using remote debug)
[Edit4] Code working with ThreadPoolExecutor:
public WorkersPool(int size) {
pool = new ThreadPoolExecutor(size, size, IDLE_WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(WORK_QUEUE_CAPACITY),
new ThreadFactory() {
#NotNull
private final AtomicInteger threadsCount = new AtomicInteger(0);
#NotNull
public Thread newThread(#NotNull Runnable r) {
final Thread thread = new Thread(r);
thread.setName("net_worker_" + threadsCount.incrementAndGet());
return thread;
}
},
new RejectedExecutionHandler() {
public void rejectedExecution(#Nullable Runnable r, #Nullable ThreadPoolExecutor executor) {
Verify.warning("new task " + r + " is discarded");
}
});
}
public void execute(#NotNull Runnable task) {
pool.execute(task);
}
public void stopWorkers() throws WorkersTerminationFailedException {
pool.shutdownNow();
try {
pool.awaitTermination(THREAD_TERMINATION_WAIT_TIME, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new WorkersTerminationFailedException("Workers-pool termination failed", e);
}
}
}
It sounds like it is a bug with an JVM's older than 6u21. There was an issue in the compiled native code for some (maybe all) OS's.
From the link:
The bug is caused by missing memory barriers in various Parker::park()
paths that can result in lost wakeups and hangs. (Note that
PlatformEvent::park used by built-in synchronization is not vulnerable
to the issue). -XX:+UseMembar constitues a work-around because the
membar barrier in the state transition logic hides the problem in
Parker::. (that is, there's nothing wrong with the use -UseMembar
mechanism, but +UseMembar hides the bug Parker::). This is a day-one
bug introduced with the addition of java.util.concurrent in JDK 5.0.
I developed a simple C mode of the failure and it seems more likely to
manifest on modern AMD and Nehalem platforms, likely because of deeper
store buffers that take longer to drain. I provided a tentative fix
to Doug Lea for Parker::park which appears to eliminate the bug. I'll
be delivering this fix to runtime. (I'll also augment the CR with
additional test cases and and a longer explanation). This is likely a
good candidate for back-ports.
Link: JVM Bug
Workarounds are available, but you would probably be best off just getting the most recent copy of Java.
I don't see any locking in the code of ThreadPoolExecutor's execute(Runnable). The only variable there is the workQueue. What sort of BlockingQueue did you provide to your ThreadPoolExecutor?
On the topic of deadlocks:
You can confirm this is a deadlock by examining the Full Thread Dump, as provided by <ctrl><break> on Windows or kill -QUIT on UNIX systems.
Once you have that data, you can examine the threads. Here is a pertinent excerpt from Sun's article on examining thread dumps (suggested reading):
For hanging, deadlocked or frozen programs: If you think your program is hanging, generate a stack trace and examine the threads in states MW or CW. If the program is deadlocked then some of the system threads will probably show up as the current threads, because there is nothing else for the JVM to do.
On a lighter note: if you are running in an IDE, can you ensure that there are no breakpoints enabled in these methods.
This deadlock probably because you run task from executor itself. For example, you submit one task, and this one fires another 4 tasks. If you have pool size equals to 4, then you just totally overflow it and last task will wait until someone of task return value. But the first task wait for all forked tasks to be completed.
As someone already mentioned, this sounds like normal behaviour, the ThreadPoolExecutor is just waiting to do some work. If you want to stop it, you need to call:
executor.shutdown()
to get it to terminate, usually followed by a executor.awaitTermination
The library code source is below (that's in fact a class from http://spymemcached.googlecode.com/files/memcached-2.4.2-sources.zip),
- a bit complicated - added protection against repeated calls of FutureTask if I'm not mistaken - but doesn't seem like deadlock prone - very simple ThreadPool usage:
package net.spy.memcached.transcoders;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import net.spy.memcached.CachedData;
import net.spy.memcached.compat.SpyObject;
/**
* Asynchronous transcoder.
*/
public class TranscodeService extends SpyObject {
private final ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 10, 60L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100),
new ThreadPoolExecutor.DiscardPolicy());
/**
* Perform a decode.
*/
public <T> Future<T> decode(final Transcoder<T> tc,
final CachedData cachedData) {
assert !pool.isShutdown() : "Pool has already shut down.";
TranscodeService.Task<T> task = new TranscodeService.Task<T>(
new Callable<T>() {
public T call() {
return tc.decode(cachedData);
}
});
if (tc.asyncDecode(cachedData)) {
this.pool.execute(task);
}
return task;
}
/**
* Shut down the pool.
*/
public void shutdown() {
pool.shutdown();
}
/**
* Ask whether this service has been shut down.
*/
public boolean isShutdown() {
return pool.isShutdown();
}
private static class Task<T> extends FutureTask<T> {
private final AtomicBoolean isRunning = new AtomicBoolean(false);
public Task(Callable<T> callable) {
super(callable);
}
#Override
public T get() throws InterruptedException, ExecutionException {
this.run();
return super.get();
}
#Override
public T get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
this.run();
return super.get(timeout, unit);
}
#Override
public void run() {
if (this.isRunning.compareAndSet(false, true)) {
super.run();
}
}
}
}
Definitely strange.
But before writing your own TPE try:
another BlockingQueue impl., e.g. LinkedBlockingQueue
specify fairness=true in ArrayBlockingQueue, i.e. use new ArrayBlockingQueue(n, true)
From those two opts I would chose second one 'cause it's very strange that offer() being blocked; one reason that comes into mind - thread scheduling policy on your Linux. Just as an assumption.
First of all, I must say that I am quite new to the API java.util.concurrent, so maybe what I am doing is completely wrong.
What do I want to do?
I have a Java application that basically runs 2 separate processing (called myFirstProcess, mySecondProcess), but these processing must be run at the same time.
So, I tried to do that:
public void startMyApplication() {
ExecutorService executor = Executors.newFixedThreadPool(2);
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
while (!(futureOne.isDone() && futureTwo.isDone())) {
try {
// I wait until both processes are finished.
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
logger.info("Processing finished");
executor.shutdown();
// Do some processing on results
...
}
myFirstProcess and mySecondProcess are classes that implements Callable<Object>, and where all their processing is made in the call() method.
It is working quite well but I am not sure that it is the correct way to do that.
Is a good way to do what I want? If not, can you give me some hints to enhance my code (and still keep it as simple as possible).
You'd be better off using the get() method.
futureOne.get();
futureTwo.get();
Both of which wait for notification from the thread that it finished processing, this saves you the busy-wait-with-timer you are now using which is not efficient nor elegant.
As a bonus, you have the API get(long timeout, TimeUnit unit) which allows you to define a maximum time for the thread to sleep and wait for a response, and otherwise continues running.
See the Java API for more info.
The uses of FutureTask above are tolerable, but definitely not idiomatic. You're actually wrapping an extra FutureTask around the one you submitted to the ExecutorService. Your FutureTask is treated as a Runnable by the ExecutorService. Internally, it wraps your FutureTask-as-Runnable in a new FutureTask and returns it to you as a Future<?>.
Instead, you should submit your Callable<Object> instances to a CompletionService. You drop two Callables in via submit(Callable<V>), then turn around and call CompletionService#take() twice (once for each submitted Callable). Those calls will block until one and then the other submitted tasks are complete.
Given that you already have an Executor in hand, construct a new ExecutorCompletionService around it and drop your tasks in there. Don't spin and sleep waiting; CompletionService#take() will block until either one of your tasks are complete (either finished running or canceled) or the thread waiting on take() is interrupted.
Yuval's solution is fine. As an alternative you can also do this:
ExecutorService executor = Executors.newFixedThreadPool();
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// interrupted
}
What is the advantage of this approach? There's not a lot of difference really except that this way you stop the executor accepting any more tasks (you can do that the other way too). I tend to prefer this idiom to that one though.
Also, if either get() throws an exception you may end up in a part of your code that assumes both tasks are done, which might be bad.
You can use invokeall(Colelction....) method
package concurrent.threadPool;
import java.util.Arrays;
import java.util.List;
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;
public class InvokeAll {
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newFixedThreadPool(5);
List<Future<java.lang.String>> futureList = service.invokeAll(Arrays.asList(new Task1<String>(),new Task2<String>()));
System.out.println(futureList.get(1).get());
System.out.println(futureList.get(0).get());
}
private static class Task1<String> implements Callable<String>{
#Override
public String call() throws Exception {
Thread.sleep(1000 * 10);
return (String) "1000 * 5";
}
}
private static class Task2<String> implements Callable<String>{
#Override
public String call() throws Exception {
Thread.sleep(1000 * 2);
int i=3;
if(i==3)
throw new RuntimeException("Its Wrong");
return (String) "1000 * 2";
}
}
}
You may want to use a CyclicBarrier if you are interested in starting the threads at the same time, or waiting for them to finish and then do some further processing.
See the javadoc for more information.
If your futureTasks are more then 2, please consider [ListenableFuture][1].
When several operations should begin as soon as another operation
starts -- "fan-out" -- ListenableFuture just works: it triggers all of
the requested callbacks. With slightly more work, we can "fan-in," or
trigger a ListenableFuture to get computed as soon as several other
futures have all finished.