In my android app I am having a thread in which I fetch data from a web service.
So normally it works well, but sometimes if the connection is too slow it kind of hangs.
So is there any way by which I can set some time say 1 min, and if the thread process is not
completed in 1 min. then I would like to stop this thread and display a message to the user that connection is weak/slow and try later.
Please help !!
This is a bad idea. The Thread.stop method is deprecated for good reasons.
I suggest you do the following: Set the network time-outs according to your preferences. If this doesn't help, I suggest that you simply throw away the reference to the thread, (ignore it, let it die out and get garbage collected) and respond with a nice message about network failure. You can very well start a new thread for trying again.
I don't know whether it is supported in Android, but this is exactly what the Future objects returned from an ExecutorService are supposed to do for you. In particular, the cancel(boolean) method can be used to interrupt the task if it has started but not finished.
The tasks should be written to be aware that they may be interrupted, and abort cleanly if they have been. Most of the framework IO methods can be interrupted, so you just need to worry about your own code.
you can use the method : Thread.interrupt();
the method Thread.stop() is deprecated
Create a stop method like this, and call interrupt subsequently.
public void stop() {
Thread currentThread= someThread;
someThread= null;
currentThread.interrupt();
}
Related
I expose an Stateless EJB as a REST service. In my POST-method, I call
Result r = longRunningBusinessMethod();
//return data
How do I go about making it possible to cancel the execution of longRunningBusinessMethod() from the client side?
I thought about creating a thread for the method, and keeping all executing threads in a hashtable together with an id, so that the user can POST his id to terminate the thread. But I am sure there must be a better solution.
Any help will be appreciated.
Interrupting working threads is always tricky and not recommended in general. One way around is to modify running business method to ask whether it should complete its execution. For instance:
public void longRunningBusinessMethod(JobContext context){
while(someCondition) {
if(shouldInterrupt(context)){
log.info("Interrupting longRunningBusinessMethod");
...
<close all the resources and terminate the job>
}
}
}
TheshouldInterrupt(context) will take job context with Job ID in it and will ask DB or Cache whether it should be interrupted. Then it's easy to change 'shouldInterrup' value in DB or Cache for this particular job via the REST API.
I think the rough design of "keeping a table of IDs" is a good starting place. Instead of terminating the thread externally, I'd probably use an ExecutorService with a thread pool, and then keep a Map<ID, Future>, so you can cancel the future. (Also making sure that each future removes itself from the map as it completes successfully or exceptionally.)
You'll also have to implement the longRunningBusinessMethod so that it contains enough places where it checks to see if it's been interrupted - canceling a future only sets the interrupted flag on the thread, it doesn't actually stop the code from executing. If your long-running methods already throw InterruptedException, it's fine as-is. Otherwise, you'll need to either add in some dummy calls, like Thread.sleep(1), or manually check Thread.interrupted() every so often, and throw the InterruptedException yourself.
I am runnning ExecutorService to perform a heavy computation, however I don't want to pollute the algorithmic class/method code with runner operations, in this case I'd like to do periodical check if it should be terminated gracefully.
I tried to search for solutions, still with no success, what I concluded is that this is not possible because only the thread itself is allowed to "autokill himself".
So my question is, if there is any way to terminate the thread "outside" of the thread by invoking some forcefull atempt to kill the thread.
If not maybe the best solution is to use aspect and intercept each iteration by adding a kill status check ?
You can call thread.interrupt(). This can cause thread to exit if it "respects" interruptions. For example if thread is blocked on IO or on wait() or on sleep() InterruptedExcption will be thrown. However if it is "blocked" on busy loop that does not check isInterrupted() flag interruption will not work.
Other way to indeed kill the thread is to call deprecated method stop(). However this is the last possibility. This method is deprecated because it indeed kills threads immediately (like kill -9) that can cause resource leaks.
Bottom line: to be able to stop threads grecefully you have to write code that is ready for this and the standard solution is to respect thread interrupts.
There sure is a way to forcefully terminate a thread: Thread#stop, but it is almost never advisable. Your idea with aspects seems quite fruitful, but if you have any sort of a main loop in your task, then consider replacing the loop with a series of submitted tasks where each task is one iteration. This will allow ExecutorService#shutdown to interrupt the processing. All state can be carried along in the instance of Runnable that is being submitted.
I haven't used the ExecutorService much. But reading the JavaDocs it appears that you submit a callable or runnable to the service. Those methods return a Future object which have a cancel method on it.
cancel(boolean mayInterruptIfRunning)
Have you tried using that?
The method thread.interrupt() stop the thread and you can call it outside the thread itself!
If you do not want to change the original implementation, you could wrap the thread. I'm not very familar with Java, so I'm sorry for the obviously not compiling example:
class ThreadWrapper extends Thread {
public ThreadWrapper(Thread t, TerminateCallback c) {
// ...
}
#Override
public void run() {
t.start(Thread.SYNCHRONOUS);
c.done(this);
}
}
You'd need to implement TerminateCallback yourself. I also assume there is a way to start a thread synchronously, Thread.SYNCHRONOUS is just a place holder. If this condition is fulfilled, I'm sure you can transfer it into valid code. :)
I have a class XYZ which extends Thread and it is also a singleton (Yes. My application needs that).
In the run method, I have something like this:
public void run() {
service.start();
}
The time it takes for service.start() is huge.
Also, my application will not always need the thread to be run but can't decide in advance so while launching the application I am starting this thread.
Now, when application doesn't need the thread, it gets completed very quickly and all I need to do is wait for thread to die.
I tried to use stop() method but came to know that it is deprecated.
See this article for alternatives to calling stop()
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
stop has been deprecated a long time ago and should not be used. Thread termination is a cooperative process in Java (i.e. the interrupted code must do something when asked to stop, not the interrupting code) - one way is to call thread.interrupt() on the thread you need to interrupt.
You then need to catch the generated interrupted exception in the running thread or check the interrupted status regularly. Once the running thread detects that is should stop what it's doing, you can then run any cleanup tasks as required and exit whatever you were doing.
Signal your thread to do it's cleanup stuff, which you said is fast anyway, then just do a Thread.join.
Your question is highly dependant on exactly what is going on in service.start(). If it's opening external resources, then naturally you can't just barge in and kill the thread without proper cleanup. The start procedure will need to be coded explicitly for interruptibility with proper cleanup.
I have an application where i need to call 3 methods in 3 seperate threads and kill them afterwards. According to the Javadoc i noticed that thread stop() and even destroy() has been deprecated. its like I start one thread after the other and then kill similarly one after the other. Is there a particular way to kill the threads because I cant use the deprecated methods
Any help much appreciated.
Thanks again
You don't kill threads. You call Thread.interrupt(), and then react to the interrupted status or InterruptedException within the thread that's being interrupted. Or, you use a volatile flag. See the official documentation for background and more info.
Even better, use a thread pool / executor instead of raw threads, as suggested in comments.
Terminating a rogue thread in a way that works every time everywhere is pretty much impossible.
If you can control the source code of the running threads, you must add a method with which you can stop the thread when you need to. Basically this method changes a boolean variable and the thread checks that value periodically to see whether or not it can continue.
public class MyTask implements Runnable {
// Set this to true when thread must stop.
private boolean mStopRequested = false;
public void run() {
while (mStopRequested == false) {
// ...
}
}
}
If you call a 3rd party libraries that do not provide such a method, then you are out of luck and have to resort to ugly kludges. Once I had to kill a long running 3rd party library call by deleting a file that was accessed by the library (it threw a FileNotFoundException and exited). And that only worked on Unix systems.
Your mileage will vary.
Use join method until the receiver finishes its execution and dies or the specified timeout expires, whatever happens first.
thread1.join(1);
thread2.join(2);
thread3.join(3);
You must handle the exception.
I am trying to stop a current thread, change the run() method, and then restart that thread. I've looked around, and most of the methods are deprecated. However, interrupt() is not. I'm not sure if that's all you need to do.
interrupt();
start();
Would that work for what I needed it to do? It says that you should never start a thread more than once, and I don't know if it means
start();
start();
Rather than what I wanted to do.
Any help is appreciated.
Thanks
No, you can't do that. Fron the java online docs:
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Don't restart a thread. You ALWAYS can rewrite your buisness logic to do this some other way. Consider using SingleThreadExecutor
In this case, you should create a Runnable object and pass it to a thread. Then you're creating different threads, but re-using the 'work' object.
Once you've started a thread, you can only interrupt it. Once you've done that, you can't start it again. See here for more details.
I'm not quite sure what you want to do, but it sounds like you have different Runnables that you want to run in sequence. In this case use a SingleThreadExecutor and submit your Runnables. It will run these in order, and so interrupting the first (successfully) will invoke the second.
I'm still not sure this is a good idea (it just doesn't sound right) and perhaps posting a more detailed problem description will give people a better idea of what you're really trying to do.
You should look into the basics of threading more. A thread can only run once. If you want to have the thread run different code, you need to create a new thread.
The interrupt() method will not stop a thread immediately (there is no supported) way to do that, it will stop only at certain points by throwing an InterruptedException().
I think you're approaching your problem in the wrong way. You cannot 'change the run() method of a Thread'. However what you probably want is to stop the previous thread and create a new one with a different run() method.
One thing to keep in mind however, is that Threads are designed to be as autonomous as possible and they don't like interference from other threads, which is why suspend() and resume() are deprecated. They create all sorts of bad behaviour depending on the circumstances and also prone to deadlocks.
You have 2 perfectly safe alternatives however:
Use wait() and notify() on a specific shared object.
Use sleep() and interrupt()
You need to decide within the run() method where it is safe to 'stop' the thread, and at that point put a wait() or sleep(). Your thread will only stop at that point.
The other thread can then do a notify() or sleep() so that the running thread is notified or interrupted. In case of interrupt() you will get an InterruptedException which you can use to terminate what you were doing in that thread.
After interrupting the old thread you can start a new thread initialised with a new Runnable implementation which has the different run() method.
Calling interrupt() will set the thread's interrupt status potentially interrupting blocking methods. This is part of a cooperative cancellation mechanism. You can't use it to force the thread to stop running.
Stopping threads has been deprecated for a reason: it is inherently dangerous as it may leave the state variables which it is manipulating in an inconsistent state.
You should not do this. Make your code from the run() method into a Runnable and submit it for execution to an Executor. This will return you a Future which you can use to retrieve its results as well as to cancel it.
If you want to reuse the same thread for other computations, use a thread pool, see for example Executors.newFixedThreadPool() and other factory methods in Executors.