54

I am having a real hard time finding a way to start, stop, and restart a thread in Java.

Specifically, I have a class Task (currently implements Runnable) in a file Task.java. My main application needs to be able to START this task on a thread, STOP (kill) the thread when it needs to, and sometimes KILL & RESTART the thread...

My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow() any future call to .execute() fails because the ExecutorService is "shutdown"...

So, how could I accomplish this?

Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
Shaitan00
  • 553
  • 1
  • 4
  • 5

9 Answers9

53

Once a thread stops you cannot restart it. However, there is nothing stopping you from creating and starting a new thread.

Option 1: Create a new thread rather than trying to restart.

Option 2: Instead of letting the thread stop, have it wait and then when it receives notification you can allow it to do work again. This way the thread never stops and will never need to be restarted.

Edit based on comment:

To "kill" the thread you can do something like the following.

yourThread.setIsTerminating(true); // tell the thread to stop
yourThread.join(); // wait for the thread to stop
Taylor Leese
  • 51,004
  • 28
  • 112
  • 141
  • Sadly I must kill/restart it ... I don't have complete control over the contents of the thread and for my situation it requires a restart... So, creating a new one is fine ... but how do I kill the current one first? – Shaitan00 Dec 10 '09 at 15:31
  • If you really wanted to 'kill' the thread never rely or attempt to use any of the api methods that seem to do that, for example kill() stop() destroy(). Instead, as Taylor suggested look at the interrupted flag: while(!Thread.currentThread().isInterrupted()){ ... } When the thread is interrupted, clean up any functions in that thread and return out of the run method and start a new thread. – John Vint Dec 10 '09 at 15:40
  • I assume there is a loop in your thread so it can check a flag to see if the thread should stop or continue executing. – Taylor Leese Dec 10 '09 at 15:45
  • 21
    **no such method setIsTerminating() in Thread** in 1.6 or 1.7. Please clarify your post - programmers must set and check flags by themselves. – tucuxi Sep 18 '12 at 07:23
  • 4
    setIsTerminating(true) would be something you implement that would tell the thead to stop. See my comment just above. – Taylor Leese Sep 20 '12 at 05:05
  • 3
    @TaylorLeese- This answer is very useful. Can you please provide more info on the Option 2 you provided.Looks like most of the discussion was on the first option. Could you please point me to some codebase or websites where I can find how to make the thread wait and continue working when it receives notification – user2821894 Apr 23 '15 at 20:28
  • @TaylorLeese I would also like to see some elaboration on Option 2, in particular, how to make it pause or resume on button clicks. – donutguy640 Oct 04 '17 at 16:08
10

Review java.lang.Thread.

To start or restart (once a thread is stopped, you can't restart that same thread, but it doesn't matter; just create a new Thread instance):

// Create your Runnable instance
Task task = new Task(...);

// Start a thread and run your Runnable
Thread t = new Thread(task);

To stop it, have a method on your Task instance that sets a flag to tell the run method to exit; returning from run exits the thread. If your calling code needs to know the thread really has stopped before it returns, you can use join:

// Tell Task to stop
task.setStopFlag(true);

// Wait for it to do so
t.join();

Regarding restarting: Even though a Thread can't be restarted, you can reuse your Runnable instance with a new thread if it has state and such you want to keep; that comes to the same thing. Just make sure your Runnable is designed to allow multiple calls to run.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Sadly the thread is waiting (listening) for incomming traffic, it is a blocking synchronous event ... so there is no "loop" within run... – Shaitan00 Dec 10 '09 at 15:40
  • 2
    @Shaitan00: If you're talking about a `ServerSocket` blocking on an `accept` call, then just have your `setStopFlag` call `close` on the socket. The `accept` call will unblock by throwing a `SocketException`. Anything else that blocks will almost certainly have an analogous exit mode. – T.J. Crowder Dec 10 '09 at 16:02
10

It is impossible to terminate a thread unless the code running in that thread checks for and allows termination.

You said: "Sadly I must kill/restart it ... I don't have complete control over the contents of the thread and for my situation it requires a restart"

If the contents of the thread does not allow for termination of its exectuion then you can not terminate that thread.

In your post you said: "My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow()..."

If you look at the source of "shutdownnow" it just runs through and interrupts the currently running threads. This will not stop their execution unless the code in those threads checks to see if it has been ineterrupted and, if so, stops execution itself. So shutdownnow is probably not doing what you think.

Let me illustrate what I mean when I say that the contents of the thread must allow for that thread to be terminated:

myExecutor.execute(new Runnable() {
 public void run() {
  while (true) {
    System.out.println("running");
  }
 }
 });
myExecutor.shutdownnow();

That thread will continue to run forever, even though shutdownnow was called, because it never checks to see if it has been terminated or not. This thread, however, will shut down:

myExecutor.execute(new Runnable() {
 public void run() {
  while (!Thread.interrupted()) {
    System.out.println("running");
  }
 }
 });
myExecutor.shutdownnow();

Since this thread checks to see whether or not it has been interrupted / shut down / terminated.

So if you want a thread that you can shut down, you need to make sure it checks to see if it has been interrupted. If you want a thread that you can "shut down" and "restart" you can make a runnable that can take new tasks as was mentioned before.

Why can you not shut down a running thread? Well I actually lied, you can call "yourThread.stop()" but why is this a bad idea? The thread could be in a synchronized (or other critical section, but we will limit ourselves to setions guarded by the syncrhonized key word here) section of code when you stop it. synch blocks are supposed to be executed in their entirity and only by one thread before being accessed by some other thread. If you stop a thread in the middle of a synch block, the protection put into place by the synch block is invalidated and your program will get into an unknown state. Developers make put stuff in synch blocks to keep things in synch, if you use threadInstance.stop() you destroy the meaning of synchronize, what the developer of that code was trying to accomplish and how the developer of that code expected his synchronized blocks to behave.

Matt Wonlaw
  • 12,146
  • 5
  • 42
  • 44
  • "It is impossible" - we have that method "setDaemon", which allows the thread to end with the last non-daemon thread. – Sam Ginrich Aug 05 '23 at 09:09
5

You can't restart a thread so your best option is to save the current state of the object at the time the thread was stopped and when operations need to continue on that object you can recreate that object using the saved and then start the new thread.

These two articles Swing Worker and Concurrency may help you determine the best solution for your problem.

ChadNC
  • 2,528
  • 4
  • 25
  • 39
  • @ChadNC- This sounds good. Can you please guide me more on how to save the current state of the object and then continue. – user2821894 Apr 23 '15 at 20:32
4

As stated by Taylor L, you can't just "stop" a thread (by calling a simple method) due to the fact that it could leave your system in an unstable state as the external calling thread may not know what is going on inside your thread.

With this said, the best way to "stop" a thread is to have the thread keep an eye on itself and to have it know and understand when it should stop.

JasCav
  • 34,458
  • 20
  • 113
  • 170
  • But the thread itself is blocking on a .receive listening for network traffic... it doesn't actually loop until it recieves something.... So, send it a dummy message to "kick the loop into gear" and set a flag? – Shaitan00 Dec 10 '09 at 15:39
0

There's a difference between pausing a thread and stopping/killing it. If stopping for you mean killing the thread, then a restart simply means creating a new thread and launching.

There are methods for killing threads from a different thread (e.g., your spawner), but they are unsafe in general. It might be safer if your thread constantly checks some flag to see if it should continue (I assume there is some loop in your thread), and have the external "controller" change the state of that flag.

You can see a little more in: http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

May I ask why you want to kill the thread and restart it? Why not just have it wait until its services are needed again? Java has synchronization mechanisms exactly for that purpose. The thread will be sleeping until the controller notifies it to continue executing.

prash
  • 896
  • 1
  • 11
  • 18
Uri
  • 88,451
  • 51
  • 221
  • 321
0

If your task is performing some kind of action in a loop there is a way to pause/restart processing, but I think it would have to be outside what the Thread API currently offers. If its a single shot process I am not aware of any way to suspend/restart without running into API that has been deprecated or is no longer allowed.

As for looped processes, the easiest way I could think of is that the code that spawns the Task instantiates a ReentrantLock and passes it to the task, as well as keeping a reference itself. Every time the Task enters its loop it attempts a lock on the ReentrantLock instance and when the loop completes it should unlock. You may want to encapsulate all this try/finally, making sure you let go of the lock at the end of the loop, even if an exception is thrown.

If you want to pause the task simply attempt a lock from the main code (since you kept a reference handy). What this will do is wait for the loop to complete and not let it start another iteration (since the main thread is holding a lock). To restart the thread simply unlock from the main code, this will allow the task to resume its loops.

To permanently stop the thread I would use the normal API or leave a flag in the Task and a setter for the flag (something like stopImmediately). When the loop encountered a true value for this flag it stops processing and completes the run method.

Gennadiy
  • 17,657
  • 4
  • 26
  • 21
  • Sadly the thread is waiting (listening) for incomming traffic, it is a blocking synchronous event ... so there is no "loop" – Shaitan00 Dec 10 '09 at 15:35
0

Sometimes if a Thread was started and it loaded a downside dynamic class which is processing with lots of Thread/currentThread sleep while ignoring interrupted Exception catch(es), one interrupt might not be enough to completely exit execution.

In that case, we can supply these loop-based interrupts:

while(th.isAlive()){
    log.trace("Still processing Internally; Sending Interrupt;");
    th.interrupt();
    try {
        Thread.currentThread().sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
Jamal
  • 763
  • 7
  • 22
  • 32
0
You can start a thread like:

    Thread thread=new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //Do you task
                    }catch (Exception ex){
                        ex.printStackTrace();}
                }
            });
thread.start();

To stop a Thread:

   thread.join();//it will kill you thread

   //if you want to know whether your thread is alive or dead you can use
System.out.println("Thread is "+thread.isAlive());

Its advisable to create a new thread rather than restarting it.

Sukirti Dash
  • 119
  • 1
  • 5
  • thread.join() does not kill your thread, it waits to be finished, blocking the calling thread until your thread finishes. However thread.interrupt() might kill the thread... – user1536873 Feb 23 '21 at 14:05