Implement a cancelable thread manager for a unique object - java

I need to manage many background threads that do something with some objects as key but only one thread can work with same object at the same time, For example while thread A is working on object A, if thread B called for working with object A, thread A should be canceled before thread B can run.
Here is my code, but when I run, The first thread doesn't stop and continues with second one:
private static ExecutorService mExecutor = Executors.newCachedThreadPool();
private static ConcurrentMap<Object, Future> mRunningTasks = new ConcurrentHashMap<>();
public static void run(final Runnable runnable, final Object key) {
Future<?> future = mRunningTasks.get(key);
if (future != null) {
future.cancel(true);
}
future = new FutureTask<>(new Runnable() {
#Override
public void run() {
//How to handle InterruptedException here ?
//while there's no potential to throw an InterruptedException
runnable.run();
mRunningTasks.remove(key);
}
}, null);
mRunningTasks.put(key, future);
mExecutor.execute((FutureTask) future);
}
What am I missing here ?
Thanks in advance.
PS:
I need a behavior like Picasso API when cancels requests using an ImageView as a key object.

The docs for Future.cancel() say that it attempts to cancel the task, but may be unsuccessful. You need to check the boolean return value to see if it actually cancelled.

There are multiple other raceconditions in your code.
ConcurrentHashMap is threadsafe, but the way you are using it is not.
You might:
* cancel a future multiple times
* add a future without canceling the previous one
* removing the wrong futures from the map
You should be more specific about you actually want to solve. There might be better solutions to that problem.

You want to kill the Thread (Thread.stop()), which is a very bad practice and deprecated for many reasons... Not only for don't have responsibility over the Thread, since it is managed by the ThreadPool, but killing it ruins the concept of atomicity of your algorithm, leaving your software in a possibly undetermined state.
You can cancel a FutureTask if it hasn't started. If you can't cancel it, it means it is already running. This occurs incredibly fast on modern multi-cores processors.
The ThreadPool is usually meant for short lived running Threads. But in your case, the right way to end the task properly is to set a volatile boolean variable in your Task Class and check it regularly to leave the method.
InterruptedException is only thrown when your Thread is waiting or sleeping, which is not present in your current demonstration code. If your Thread actually is waiting or sleeping, then send a .notify() to the monitor Object to interrupt it, and catch the Exception in a try {} catch()

There are two primary problems here 1) the run method needs to be declared synchronised (avoids race conditions when checking the state of things) and 2) future.cancel is not capable of halting work that has already started. So add your own guards/cancelling mechanism to the runnables.
That said, the cleanest solution is to avoid the need to cancel in the first place, however there is not enough domain detail in this question to verify if that would be feasible. A common pattern for this kind of problem is to return a promise from run and cache the promises. A promise is a thread safe container object for the result of an asynchronous operation. If the same work is scheduled twice then the same promise may be returned. If a promise has a value it would be possible to see how old the value was to determine the scheduling behaviour, such as return the old value, return the old value and schedule an update of the value behind the scenes or throw the old value away as too old and fetch a clean value.

Related

Thread with capability of stopping it in any duration of time

is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
I wrote something like this
public class ThreadRunner {
private ExecutorService threadPoolExecutor;
ThreadRunner() {
threadPoolExecutor = Executors.newSingleThreadExecutor();
}
public void startThread(String endPoint, ProgressBar progressBar) {
Runnable task = () -> {
// some code which saves images from URL (1230 images) and updates progress bar
};
threadPoolExecutor.execute(task);
}
public void stopThread() {
threadPoolExecutor.shutdownNow();
}
}
Thread runs correctly, images are being saved, progress bar being updated, but when I want to stop thread (or maybe even pause process of saving if possible) by calling ThreadRunner class's method - nothing happens.
Am I doing something wrong - or most likely - what am I doing wrong?
is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
You can implement such a thing yourself, but there is no generic support available for it, unless you count the long-deprecated Thread.stop() methods. Under no circumstances should you use those methods, but do read their API docs for a discussion of why they are deprecated and what you can do instead. You can find a longer-form version of the discussion in Java's technical notes.
The bottom line is that the computation you want to be able to stop needs to periodically check some shared variable or built-in condition to determine whether to do so. You arrange for that variable to be set when you want the thread to stop, and if you need to block until it does stop then you join() it. Under some circumstances, it can be helpful to interrupt() the thread to get it to check the variable (or being interrupted can itself serve as the termination condition). The user-facing end of this can be wrapped up in a method.
In any case, an ExecutorService cannot give you a handle on this. Requesting such a service to shut down will prevent it from dispatching any more tasks, but there is no safe, general-purpose mechanism by which it could force a premature shutdown of tasks that are already running.
Once started, a thread will run until Runnable.run() exits. Due to several issues you should never use Thread.stop() or Thread.interrupt().
Instead, you will have to implement your own logic for exit/pause. A few suggestions:
For stopping the thread, you can make a boolean variable shouldExit. In your thread, check this variable every now and then, and just do "return" or break the for/while loop when it becomes true. Setting this variable from another thread should now make the downloader exit. If necessary, you should surround access to this variable with synchronized block as to prevent any race conditions.
For pausing the thread, you can use a similar approach. When you set a certain variable to true (e.g. isPaused), make the thread react by going into an Object.sleep(). This way, it won't consume any CPU during sleep. You can then use Object.notify() from another thread to "kick" the sleeping thread out ouf sleep. You will need a synchronized block here, too.

Cancelling group of threads if one of the thread finishes

I am trying to figure out the solution for a scenario of cancelling a group of threads if one of the Thread finishes the task successfully.
The scenario is like this: Lets say a group of threads are working on a task to find a String in a file and if any of the thread finds the String, the remaining treads should stop execution.
Using 1.5 concurrency we can achieve this, but prior to JDK 1.5 if we want to achieve this kind of scenario, then how can we do that?
For Java 2 Platform, Standard Edition 1.4 SDK or higher you could use exception chaining.
How about just splitting up the thread's task into smaller chunks and checking for a stop condition in the loop?
You could interrupt the threads and in each thread check for the interrupted flag:
public class Job implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// perform stuff
}
}
}
In the shutdown-code you call
thread.interrupt();
for each other thread.
The advantage compared to a stop-flag is that your threads will also drop out of any blocking calls.
The good way to stop a thread is to have it periodically check a flag that indicates whether or not it should continue. The java Thread class already has such a facility, called interrupts, that is useful in many scenarios, as bennihepp points out in his answer. See the javadoc for the Thread class and the interrupt() and isInterrupted() methods in particular.
In the following example the runnable class makes sure that all of the instances halt (soon) after one instance finishes. It is worth noting that you should keep your unit of work (one iteration of the loop) small enough.
public class MyRunnable implements Runnable {
private static boolean shouldStop = false;
public void run() {
// allocate required resources
while (!MyRunnable.shouldStop) {
// do work
if (/* some condition to indicate completion */)
MyRunnable.shouldStop = true;
}
// release any allocated resources
}
}
This simple example assumes all threads wrap the same type of a runnable object. Once one sets the shouldStop flag, all others also stop. It would be quite trivial to extend the example to also facilitate interruptions.

Terminated Thread Revival

I am storing a bunch of threads objects in an arraylist. I want to be able to start these threads at random. Same thread can be started more than once. Before I start a thread object, I check on whether the thread is alive, and if they have either of NEW or TERMINATED status. This restriction because, I don't want to disturb the 'busy' threads. Now, for NEW threads, this works fine. But for TERMINATED thread, I get an exception.
When a thread ends, shouldn't it go back to being 'new'? Or are threads 'disposable' - like use once and done?
As it says in the documentation for Thread.start(), "It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution."
It is better for you to keep hold of Runnable instances and implement your own logic for keeping track of when the execution of each one of them finishes. Using an Executor is probably the simplest way to run the Runnables.
You should probably be using the awesome stuff provided in java.util.concurrent. Based on your description, ThreadPoolExecutor sounds like a good thing to check out.
This is the way I did it
class GarbageDisposalThread extends Thread {
public void start() {
try {
super.start();
} catch( IllegalThreadStateException e ) {
this.arrayList.remove(this);
this.arrayList.add( new GarbageDisposalThread( this.arrayList ));
}
}
private GarbageDisposalThread() {
}
public GarbageDisposalThread( ArrayList<Whatever> arrayList ) {
this.arrayList = arrayList;
this.start();
}
public void run() {
// whatever the code
}
private ArrayList<Whatever> arrayList = null;
}
that's it!
you can change the code according to your needs :P
Java threads cannot be restarted.
From the javadoc:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
See the Thread.start() javadoc for more information.
There are other ways to accomplish what you are trying to do. For example, you could use new Threads that continue the work that was done in the Thread that has finished execution. You may also want to investigate the java.util.concurrent package.
From another post...
You could use ThreadPoolExecutor, which would allow you to pass in tasks and let the service assign a thread to a task. When the task is finished, the thread goes idle until it gets the next task.
So, you don't restart a thread, but you would redo/resume a task.

How does one stop a thread without a stop() method?

I have question about the Java threads. Here is my scenario:
I have a thread calling a method that could take while. The thread keeps itself on that method until I get the result. If I send another request to that method in the same way, now there are two threads running (provided the first did not return the result yet). But I want to give the priority to the last thread and don't want to get the results from the previously started threads. So how could I get rid of earlier threads when I do not have a stop method?
The standard design pattern is to use a local variable in the thread that can be set to stop it:
public class MyThread extends Thread {
private volatile boolean running = true;
public void stop() {
running = false;
}
public void run() {
while (running) {
// do your things
}
}
}
This way you can greacefully terminate the thread, i.e. without throwing an InterruptedException.
The best way really depends on what that method does. If it waits on something, chances are an interrupt will result in an InterruptedException which you handle and cleanly exit. If it's doing something busy, it won't:
class Scratchpad {
public static void main(String[] a) {
Thread t = new Thread(new Runnable() {
public void run() {doWork();}
});
t.start();
try {
Thread.sleep(50);
} catch (InterruptedException ie) {}
t.interrupt();
}
private static void doWork() {
for ( long i = 1; i != 0; i *=5 );
}
}
In the case above, the only viable solution really is a flag variable to break out of the loop early on a cancel, ala #inflagranti.
Another option for event-driven architectures is the poison-pill: if your method is waiting on a blocking queue for a new item, then you can have a global constant item called the "poison-pill" that when consumed (dequeued) you kill the thread:
try {
while(true) {
SomeType next = queue.take();
if ( next == POISON_PILL ) {
return;
}
consume(next);
}
} catch //...
EDIT:
It looks like what you really want is an executor service. When you submit a job to an executor service, you get back a Future which you can use to track results and cancel the job.
You can interrupt a Thread, its execution chain will throw an InterruptedException most of the time (see special cases in the documentation).
If you just want to slow down the other thread and not have it exit, you can take some other approach...
For one thing, just like exiting you can have a de-prioritize variable that, when set, puts your thread to sleep for 100ms on each iteration. This would effectively stop it while your other thread searched, then when you re-prioritize it it would go back to full speed.
However, this is a little sloppy. Since you only ever want one thing running but you want to have it remember to process others when the priority one is done, you may want to place your processing into a class with a .process() method that is called repeatedly. When you wish to suspend processing of that request you simply stop calling .process on that object for a while.
In this way you can implement a stack of such objects and your thread would just execute stack.peek().process(); every iteration, so pushing a new, more important task onto the stack would automatically stop any previous task from operating.
This leads to much more flexible scheduling--for instance you could have process() return false if there is nothing for it to do at which point your scheduler might go to the next item on the stack and try its' process() method, giving you some serious multi-tasking ability in a single thread without overtaxing your resources (network, I'm guessing)
There is a setPriority(int) method for Thread. You can set the first thread its priority like this:
Thread t = new Thread(yourRunnable);
t.start();
t.setPriority(Thread.MIN_PRIORITY); // The range goes from 1 to 10, I think
But this won't kill your thread. If you have only two threads using your runnable, then this is a good solution. But if you create threads in a loop and you always sets the priority of the last thread to minimum, you will get a lot of threads.
If this is what is application is going to do, take a look at a ThreadPool. This isn't an existing class in the Java API. You will have create one by yourself.
A ThreadPool is another Thread that manages all your other Threads the way you want. You can set a maximum number of running Threads. And in that ThreadPool, you can implement a system that manages the Thread priority automatically. Eg: You can make that older threads gain more priority, so you can properly end them.
So, if you know how to work with a ThreadPool, it can be very interesting.
According to java.lang.Thread API, you should use interrupt() method and check for isInterrupted() flag while you're doing some time-consuming cancelable operation. This approach allows to deal with different kind of "waiting situations":
1. wait(), join() and sleep() methods will throw InterruptedExcetion after you invoke interrupt() method
2. If thread blocked by java.nio.channels.Selector it will finish selector operation
3. If you're waiting for I/O thread will receive ClosedByInterruptException, but in this case your I/O facility must implement InterruptibleChannel interface.
If it's not possible to interrupt this action in a generic way, you could simply abandon previous thread and get results from a new one. You could do it by means of java.util.concurrent.Future and java.util.concurrent.ExecutorService.
Cosider following code snippet:
public class RequestService<Result> {
private ExecutorService executor = Executors.newFixedThreadPool(3);
private Future<Result> result;
public Future<Result> doRequest(){
if(result !=null){
result.cancel(true);
}
result = executor.submit(new Callable<Result>() {
public Result call() throws Exception {
// do your long-running service call here
}
});
return result;
}
}
Future object here represents a results of service call. If you invoke doRequest method one more time, it attempts to cancel previous task and then try to submit new request. As far as thread pool contain more than one thread, you won't have to wait until previous request is cancelled. New request is submitted immediately and method returns you a new result of request.

Java 5: java.util.concurrent.FutureTask - Semantics of cancel() and done()

I am currently hunting a nasty bug in a multi-threaded environment using FutureTasks and Executors. The basic idea is this to have a fixed number of threads execute individual FutureTasks that compute a result that is to be displayed in a a table (never mind the GUI aspect here).
I have been looking at this for so long, I am beginning to doubt my sanity.
Consider this piece of code:
public class MyTask extends FutureTask<Result> {
private String cellId;
...
protected void done() {
if (isCancelled()) return;
try {
Result r = get(); // should not wait, because we are done
... // some processing with r
sendMessage(cellId, r);
} catch (ExecutionException e) { // thrown from get
...
} catch (InterruptedException e) { // thrown from get
...
}
}
...
}
When done() is called by an Executor handling an instance of MyTask, I check if I got there, because the task was cancelled. If so, I skip all remaining activities, especially I do not call sendMessage().
The documentation for FutureTask.done() says:
Protected method invoked when this task transitions to state isDone (whether normally or via cancellation). The default implementation does nothing. Subclasses may override this method to invoke completion callbacks or perform bookkeeping. Note that you can query status inside the implementation of this method to determine whether this task has been cancelled.
(API Reference)
But what I do not get from the documentation of FutureTask are the semantics while done() is being executed. What if I pass the isCancelled() check at the beginning, but right after that some other thread calls my cancel() method? Will that cause my task to change its mind and reply isCancelled() == true from then on?
If so, how would I later know if the the message was sent? Looking at isDone() would just tell me that execution of the task was finished, but as isCancelled() were true then as well, I could not know if it got to send the message out in time.
Maybe this is obvious, but I do not really see it right now.
FutureTask#done() is called no more than once for any given instance, and it's only called for one reason -- run() completed either with or without error, or cancel() ran before either of the preceding events occurred. The record of completion by any of these outcomes is latching. The reason a FutureTask completed can't change, regardless of competing events seemingly happening "at the same time."
Hence, within FutureTask#done() only one of isCancelled() or isDone() will return true then and forever more. It's difficult to distinguish between isDone() reporting true by way of error or successful completion. You can't override set() or setException(Throwable) decisively, as both delegate to the inner AQS to decide whether the attempt to record a successful yielding of a value or encountering an exception should stick. Overriding either method only lets you know that it was called, but you can't observe the decision made by the base implementation. If either event occurs "too late"—say, after cancellation—the attempt to record the value or the exception will be ignored.
Studying the implementation, the only way I see to discern a non-canceled successful outcome from an error is to bite the bullet and call get().
From the API (emphasis mine):
public boolean cancel(boolean mayInterruptIfRunning)
Description copied from interface: Future
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason.
So FutureTask is working off the assumption that you cannot cancel a task when it has transitioned to the isDone stage.
Why not send the message "outside" of the task, based on the outcome of the Future<V> object returned by an ExecutorService? I've used this pattern and it seems to work well: Submit a bunch of Callable<V> tasks through an ExecutorService. Then, for each primary task, submit a secondary task that waits on the Future<V> of the primary task and does some follow-up action (like send a message) only if the Future<V> indicates that the primary task completed successfully. There is no guesswork with this approach. When the call to Future<V>.get() returns, you're guaranteed that the task has reached a terminal state, as long as you don't call the version of get that takes a timeout argument.
If you take this approach, you should use two separate ExecutorService instances: one for the primary tasks and one for the secondary ones. This is to prevent deadlocks. You don't want secondary tasks to start up and potentially block primary tasks from starting when the thread pool size is limited.
There's no need to extend FutureTask<V> at all. Just implement your tasks as Callable<V> objects. But if for some reason you want to detect if the task was canceled from within the Callable<V> code, just check the interrupt status of the thread with Thread.interrupted().
I suggest to write a small test case which allows you to call cancel() while your Future instance hangs in done() and see what happens.

Categories