I've implemented subscription in my Java app. When new subscriber added, the application creates new task (class which implements Runnable to be run in the separate thread) and it is added to the ExecutorService like:
public void Subscribe()
{
es_.execute(new Subscriber(this, queueName, handler));
}
//...
private ExecutorService es_;
Application may register as many subscribers as you want. Now I want implement something like Unsubscribe so every subscriber has an ability to stop the message flow. Here I need a way to stop one of the tasks running in the ExecutorService. But I don't know how I can do this.
The ExecutorService.shutdown() and its variations are not for me: they terminates all the tasks, I want just terminate one of them. I'm searching for a solution. As simple as possible. Thanks.
You can use ExecutorService#submit instead of execute and use the returned Future object to try and cancel the task using Future#cancel
Example (Assuming Subscriber is a Runnable):
Future<?> future = es_.submit(new Subscriber(this, queueName, handler));
...
future.cancel(true); // true to interrupt if running
Important note from the comments:
If your task doesn't honour interrupts and it has already started, it will run to completion.
Instead of using ExecutorService.execute(Runnable) try using Future<?> submit(Runnable). This method will submit the Runnable into the pool for execution and it will return a Future object. By doing this you will have references to all subscriber threads.
In order to stop particular thread just use futureObj.cancel(true). This will interrupt the running thread, throwing an InterruptedException. The subscriber thread should be coded such way it will stop processing in the case of this exception (for example Thread.sleep(millis) with wrapper try / catch block for the whole method).
You cand find more information on the official API:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
Related
I need to execute only a a single thread with the ability to cancel it. I found that I can achieve this using Future<T>s. Right now I use it like this:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Void> future = executorService.submit(copyCallable);
executorService.shutdown();
Since ExecutorServices are usually used to manage a multiple threads, I was wondering if there was a more efficient way to achieve this without creating one. Thanks.
Interryprion is implemented by both Thread and calling method. Your thread need to listen for InterruptedException or check interruption flag at convenient points in time. Calling code should call t.interrupt() for notifying Thread that it should stop.
I try to work with Java's FutureTask, Future, Runnable, Callable and ExecutorService types.
What is the best practice to compose those building blocks?
Given that I have multiple FutureTasks and and I want to execute them in sequence.
Ofcourse I could make another FutureTask which is submitting / waiting for result for each subtask in sequence, but I want to avoid blocking calls.
Another option would be to let those subtasks invoke a callback when they complete, and schedule the next task in the callback. But going that route, how to I create a proper outer FutureTask object which also handles exceptions in the subtask without producing that much of a boilerplate?
Do I miss something here?
Very important thing, though usually not described in tutorials:
Runnables to be executed on an ExecutorService should not block. This is because each blocking switches off a working thread, and if ExecutorService has limited number of working threads, there is a risk to fall into deadlock (thread starvation), and if ExecutorService has unlimited number of working threads, then there is a risk to run out of memory. Blocking operations in the tasks simply destroy all advantages of ExecutorService, so use blocking operations on usual threads only.
FutureTask.get() is blocking operation, so can be used on ordinary threads and not from an ExecutorService task. That is, it cannot serve as a building block, but only to deliver result of execution to the master thread.
Right approach to build execution from tasks is to start next task when all input data for the next task is ready, so that the task do not have to block waiting for input data. So you need a kind of a gate which stores intermediate results and starts new task when all arguments have arrived. Thus tasks do not bother explicitly to start other tasks. So a gate, which consists of input sockets for arguments and a Runnable to compute them, can be considered as a right building block for computations on ExcutorServices.
This approach is called dataflow or workflow (if gates cannot be created dynamically).
Actor frameworks like Akka use this approach but are limited in the fact that an actor is a gate with single input socket.
I have written a true dataflow library published at https://github.com/rfqu/df4j.
I tried to do something similar with a ScheduledFuture, trying to cause a delay before things were displayed to the user. This is what I come up with, simply use the same ScheduledFuture for all your 'delays'. The code was:
public static final ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
public ScheduledFuture delay = null;
delay = scheduler.schedule(new Runnable() {
#Override
public void run() {
//do something
}
}, 1000, TimeUnit.MILLISECONDS);
delay = scheduler.schedule(new Runnable() {
#Override
public void run() {
//do something else
}
}, 2000, TimeUnit.MILLISECONDS);
Hope this helps
Andy
The usual approach is to:
Decide about ExecutorService (which type, how many threads).
Decide about the task queue (for how long it could be non-blocking).
If you have some external code that waits for the task result:
* Submit tasks as Callables (this is non blocking as long as you do not run out of the queue).
* Call get on the Future.
If you want some actions to be taken automatically after the task is finished:
You can submit as Callables or Runnables.
Just add that you need to do at the end as the last code inside the task. Use
Activity.runOnUIThread these final actions need to modify GUI.
Normally, you should not actively check when you can submit one more task or schedule callback in order just to submit them. The thread queue (blocking, if preferred) will handle this for you.
I am working on a multithreading app in Java 5. When it executes it starts several executor services and it has to run for a very long time. I have a monitor service that keeps a check on the state of each created executor. I have read that the executor service may only have the following states:
running,
shutting down and
terminated.
In case anything strange happens during the execution,
I have subclassed my own FutureTask class and overriden the methods:
setException and,
done (anything unusual like ExecutionException and
InterruptedException are caugth here)
I have a case where an Executor service throws an ExecutionException (in my own FutureTask class). The ExecutionException is caught and logged but my executor service is not logging in anything anymore. My monitor service is outputing the executor service is still alive.
Maybe it has to do with the fact that my FutureTask has reached the state done?
What is the best way to manage this?
Is it possible to restart the executor service?
It looks like the FutureTask state affects the Executor service, can I use the FutureTask's state to know the state of the Executor service.
Thanks for your help,
Usually handling exception is best done by the task itself. If your task throws an exception it is finished even if its a scheduled task (it won't run again). In fact if there is any work work you want done after the task has completed its often best done by the same thread in the task also. i.e. only return when there is almost nothing left to do.
EDIT: To prevent a recurring task from dying you can use a try/catch block.
Runnable run = new Runnable() {
public void run() {
try {
// do something which might throw an Exception
} catch(Exception e) {
log.error(e);
}
}
};
scheduledExecutorService.scheduleAtFixedRate(run, delay, period, unit);
If you don't catch the exception and log it, it will be stored in the FutureTask and you have to remember to log it there and restart the task remembering how often to runt he task.
BTW: A task doesn't impact the state of an ExecutorService unless has a reference to it calls it directly. (it won't happen unexpectedly)
BTW2: With the release of Java 7, more than five years after Java 6, its about time to consider migrating from Java 5.0 which has been end of life for over three years.
I start one thread to download contents from the internet, at one time, the thread is downloading one file, and then i want it stop and begin to download another file, what should i do? should i count on the concurrency mechanism in java?
You can start your thread using a single-thread executor, then when you kill it (gracefully I hope) and start a new one it will ensure that it's using the same thread.
// Suppose you have a DownloadFile class that implements Runnable
DownloadFile task1 = new DownloadFile();
...
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Boolean> future = exec.submit( task1, Boolean.TRUE );
...
// Cancel the task
future.cancel();
// Give the executor another task
DownloadFile task2 = new DownloadFile();
...
exec.submit( task2, Boolean.TRUE );
Other useful docs:
Future
ExecutorService
Stopping thread using stop() method is not recommended.
I start one thread to download
contents from the internet, at one
time, the thread is downloading one
file, and then i want it stop and
begin to download another file, what
should i do?
You need to use the sleep( ) method of Thread class to pause the same thread for some specified milliseconds before you can continue the work with the same thread.
Note : Once the thread has been stopped, it can't resume its work. It will result in IllegalThreadStateException.
See :
Why are Thread.stop() , Thread.suspend() and Thread.resume() Deprecated ?
How to stop a java thread gracefully ?
To interrupt a thread from a current processing and redirect it to something else is a classic synchronization problem. This is done as follows:
Have a job queue. The jobs in the job queue [or more specifically the objects in the job queue] should have a method [say process()] that the thread will execute. The thread generally does not know the details of the process() method. It only cares that it has to run the process() method.
The thread must wait on the job queue. This is done as follows:
Job j = null;
synchronized(jobQueueInstance)
{
if(jobQueueInstance.isEmpty())
{
jobQueueInstance.wait();
}
j = jobQueueInstance.poll(); //get the job from the head of the queue
}
try
{
j.process();
}
catch(InterruptedException ex)
{
//thread is interrupted, means it needs to abandon this job and fetch a new one from the queue
}
I hope this helps. However I have omitted a few things to oversimplify the problem:
I have omitted the Job class declaration, I guess it will either be an interface or an abstract class.
I have also omitted the part where some other thread will add a new Job() and notify() on the jobQueueInstance.
Also omitted the part about the thread that will interrupt() the "busy" job-running thread.
NOTE Threads 3 and 4 can be the same thread.
You should place a timeout on your download using the software for downloading. This usually results in an Exception which you can catch, clean up what you are doing and continue on.
Unless the software you are using supports interrupts or time out settings, there is no safe way to force this to happen externally. You can use stop() safely provided your intention is to shutdown at soon as possible. (In which case System.exit() is a better option)
If you have a library which you have no choice but to kill, you need to run it in a separate process and kill the whole process. This will ensure any resources used will be cleaned up by the OS. (Assuming it hasn't left temporary files etc. ;)
I can't use shutdown() and awaitTermination() because it is possible new tasks will be added to the ThreadPoolExecutor while it is waiting.
So I'm looking for a way to wait until the ThreadPoolExecutor has emptied it's queue and finished all of it's tasks without stopping new tasks from being added before that point.
If it makes any difference, this is for Android.
Thanks
Update: Many weeks later after revisiting this, I discovered that a modified CountDownLatch worked better for me in this case. I'll keep the answer marked because it applies more to what I asked.
If you are interested in knowing when a certain task completes, or a certain batch of tasks, you may use ExecutorService.submit(Runnable). Invoking this method returns a Future object which may be placed into a Collection which your main thread will then iterate over calling Future.get() for each one. This will cause your main thread to halt execution until the ExecutorService has processed all of the Runnable tasks.
Collection<Future<?>> futures = new LinkedList<Future<?>>();
futures.add(executorService.submit(myRunnable));
for (Future<?> future:futures) {
future.get();
}
My Scenario is a web crawler to fetch some information from a web site then processing them. A ThreadPoolExecutor is used to speed up the process because many pages can be loaded in the time. So new tasks will be created in the existing task because the crawler will follow hyperlinks in each page. The problem is the same: the main thread do not know when all the tasks are completed and it can start to process the result. I use a simple way to determine this. It is not very elegant but works in my case:
while (executor.getTaskCount()!=executor.getCompletedTaskCount()){
System.err.println("count="+executor.getTaskCount()+","+executor.getCompletedTaskCount());
Thread.sleep(5000);
}
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
Maybe you are looking for a CompletionService to manage batches of task, see also this answer.
(This is an attempt to reproduce Thilo's earlier, deleted answer with my own adjustments.)
I think you may need to clarify your question since there is an implicit infinite condition... at some point you have to decide to shut down your executor, and at that point it won't accept any more tasks. Your question seems to imply that you want to wait until you know that no further tasks will be submitted, which you can only know in your own application code.
The following answer will allow you to smoothly transition to a new TPE (for whatever reason), completing all the currently-submitted tasks, and not rejecting new tasks to the new TPE. It might answer your question. #Thilo's might also.
Assuming you have defined somewhere a visible TPE in use as such:
AtomicReference<ThreadPoolExecutor> publiclyAvailableTPE = ...;
You can then write the TPE swap routine as such. It could also be written using a synchronized method, but I think this is simpler:
void rotateTPE()
{
ThreadPoolExecutor newTPE = createNewTPE();
// atomic swap with publicly-visible TPE
ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(newTPE);
oldTPE.shutdown();
// and if you want this method to block awaiting completion of old tasks in
// the previously visible TPE
oldTPE.awaitTermination();
}
Alternatively, if you really no kidding want to kill the thread pool, then your submitter side will need to cope with rejected tasks at some point, and you could use null for the new TPE:
void killTPE()
{
ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(null);
oldTPE.shutdown();
// and if you want this method to block awaiting completion of old tasks in
// the previously visible TPE
oldTPE.awaitTermination();
}
Which could cause upstream problems, the caller would need to know what to do with a null.
You could also swap out with a dummy TPE that simply rejected every new execution, but that's equivalent to what happens if you call shutdown() on the TPE.
If you don't want to use shutdown, follow below approaches:
Iterate through all Future tasks from submit on ExecutorService and check the status with blocking call get() on Future object as suggested by Tim Bender
Use one of
Using invokeAll on ExecutorService
Using CountDownLatch
Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)
invokeAll() on executor service also achieves the same purpose of CountDownLatch
Related SE question:
How to wait for a number of threads to complete?
You could call the waitTillDone() on Runner class:
Runner runner = Runner.runner(10);
runner.runIn(2, SECONDS, runnable);
runner.run(runnable); // each of this runnables could submit more tasks
runner.waitTillDone(); // blocks until all tasks are finished (or failed)
// and now reuse it
runner.runIn(500, MILLISECONDS, callable);
runner.waitTillDone();
runner.shutdown();
To use it add this gradle/maven dependency to your project: 'com.github.matejtymes:javafixes:1.0'
For more details look here: https://github.com/MatejTymes/JavaFixes or here: http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html
Try using queue size and active tasks count as shown below
while (executor.getThreadPoolExecutor().getActiveCount() != 0 || !executor.getThreadPoolExecutor().getQueue().isEmpty()){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}