Can I start a thread again after it has died? - java

If I use start() on a Thread object and the run() method returns, is it possible to call start() again?
eg,
MyThread myThread = new MyThread();
myThread.start();
// run method executes and returns in 2 seconds
// sleep for 5 seconds to make sure the thread has died
myThread.start();
I'm just wondering because my code is throwing IllegalThreadStateExceptions, so want to know if it's because you can't do the above.

No, you can't. And the Javadoc for the Thread.start() method tells you that!

From a comment:
Is there anything else I could do to re-start a thread?
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.

Nope.
From the Javadoc for java.lang.Thread:
It is never legal to start a thread
more than once.

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.

Perhaps there is a better way of doing this if you want the thread to stop and restart multiple times. I have a tile caching thread in C++ that does something similar; it pauses when it's finished, and unpaused when it's needed again. I am new to Java, but from what I can tell, you can use Object.wait() to pause, and Object.notify() to resume threads. Maybe you could check those out in the documentation and redesign your thread to pause and resume instead of exiting.

Related

problem using isAlive(),Interrupt() and stop() methods of a Thread inside ExecuterService

i have found that isAlive() method is not working when executing a thread using ExecuterService.
And interrupt() and stop() method is also not working.
The code i used:
Thread t1=new Thread(()->{
try{
Thread.sleep(10000);
} catch(InterruptedExeception ie){
System.out.println("Interrupted");
}
Thread.sleep(5000);
System.out.println("It's Done");
});
ExecuterService excuter=Executers.newSingleThreadExecuter();
excuter.execute(t1);
Thread.sleep(2000);
System.out.println(t1.isAlive());
Thread.sleep(2000);
t1.interrupt();
t1.stop();
My expected output is :
true
Interrupted
Actual output is :
false
It's Done
I need reason for this behavior. And I want to know what is the solution for the problem and how I use these methods when a Thread is running inside a ThreadPool.
The stop() method does not work. You can't stop threads like this. A thread needs to opt into allowing itself to be stopped; you'd for example update a (volatile, or AtomicBoolean-style) boolean, and the thread runs a loop, and on each loop, checks that boolean; if it's false, it ends. There is no way to stop arbitrary threads in their tracks. At all. You can google for information about why Thread.stop is deprecated (and effectively doesn't work at all anymore, even though the method is still around, primarily as vehicle for the documentation on why you can't do that anymore).
Threads implement runnable, which is why you're even allowed to pass that thread to the executor method, but the entire thread infra isn't being used at all. You should update this code to be Runnable r = () -> { ... } and pass that. Your code as written is misleading you into thinking that's the thread that is being run. It's not, which is why you're getting false for .isAlive().
Executors as a rule don't expose the way they do the job, they just do it. If you want to check if the job is running, set a (volatile, or AtomicBoolean) boolean to true upon entry, and to false upon exit. Alternatively, don't bother with an executor service, just start your thread, if you really want to use thread functionalities such as .isAlive().
t1 is not a thread.
t1 is a Thread instance, but a Thread instance is not the same thing as a thread, and the way you are using t1, no thread is ever created. Think of a Thread instance as a handle that you use to create and control a thread. The thread would be created if your program called t1.start(), and then the t1.isAlive() and t1.interrupt() and t1.stop() calls all would operate on that new thread.
Besides being a Thread instance, t1 also happens to be a Runnable instance, which is what the executer.execute(...) call wants. Being a Runnable just means that t1 has a run() method. There are various ways that run() method could be called:
You could start the thread, t1.start(), in which case, the new thread would call it,
You could (you did) give it to an Executor. When you do that, the Executor arranges to have one of its worker threads call your run() method.
You could simply call it -- t1.run() -- which is no different from calling any other method that your code defines.
You could pass it to any other library method that wants a Runnable. (I don't know how many there are, maybe a lot.)
If you want t1.run() to be called in a thread that your code can control, then call t1.start() to create that thread. If you want it to be called by an executor service, whose threads you should not attempt to control, then do what you did: call excuter.execute(t1);
Just don't do both. That probably isn't what you want.
P.S., If you want to continue using the Executor service, then you probably should change your declaration of t1. Since it only needs to be a Runnable in that case, you can write:
Thread t1=new Runnable(()->{
...
});
That way, people reading your code won't scratch their heads and wonder whether you knew what you were doing.

Is there standard implementation for thread block/resume in java SE?

I need to block execution of a thread until resumed from another thread. So I wrote my own implementation using wait() method. Which seems to be working, but it is far from simple.
Is there any ready to use solution? Preferably in java SE 6? Or do I have to use my own implementation? I couldn't find any.
Update
More specifically. I need work->block->external release->work->end behavior from thread 1 and ability to release block from thread 2.
have a a look at the classes in java.util.conucurrent ...
CountDownLatch might be a solution for your problem if i understand your problem correctly.
I need to block execution of a thread until resumed from another thread.
Not enough information. Do you need an on/off switch that is controlled entirely by one thread and obeyed by the other? That might be a good application for a Turnstile: Pause thread from another thread(s) and also stop/start it yet from another thread
Or do you need "one-shot" behavior? (i.e., the "background" thread does one thing each time the "foreground" thread gives it permission to go.) That would be a good application for a java.util.concurrent.Semaphore.
Or, do you need some other behavior?
using an ExecutorService and calling invokeAll might also be an option.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html
this way lets you also specify a timeout in which all tasks should have been finished. Which is generally a very good idea, if you want to have a responsive application.
Inspired by other answers, I found two solutions:
First:
Create Semaphore with no (0) permits:Semaphore semaphore = new Semaphore(0); in first thread. And share reference to it with your second thread.
Do some work in the first thread and call semaphore.acquire(); when you wish to stop execution.
Some time later call semaphore.release(); from second thread to unblock the first one.
Second:
Create CountDownLatch with initial count 1: CountDownLatch countDownLatch = new CountDownLatch (1); And again, share reference to it with both threads.
Call countDownLatch.await(); when you wish to block execution of the first thread.
The first thread can be resumed by calling countDownLatch.countDown(); somewhere in the second thread.

java: Stop the Singleton thread

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.

Stopping and Restarting a Thread

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.

How can I have a thread tell the method that started it when it has completed doing its setup?

I have a method that starts a thread, and I want to have the method block until the thread finishes its setup stage, or else face a race condition.
I know I want to use wait notify, but I don't know how to own the monitor and so on.
I generally use a Count down latch if only the starting thread needs to wait.
There are examples there but I can throw up a quicky example if you need it.
Or you could use a barrier if multiple threads are likely to use thread and need to know when it is initialized.
Move your "setup stage" out of run() and into an init() method.
MyRunnableClass mrc = new MyRunnableClass();
mrc.init();
Thread t = new Thread(mrc);
t.start();
Edit: Or as #Buhb noted in the comments below, just put it in the constructor. Years of C++ makes old habits die hard.

Categories

Resources