4

I have a Java application that I CAN'T EDIT that starts a java.lang.Thread that has this run() method:

public void run(){
   while(true){
     System.out.println("Something");
   }
}

At a certain point in time I want to stop it. If I use Thread.interrupt() it doesn't work. If I use Thread.stop() it works, but this method is deprecated (so its use is discouraged as it may be removed from JVM in new releases).

How to stop such uninterruptible threads in Java?

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
Marco Vasapollo
  • 509
  • 5
  • 16
  • It's unclear if you want to stop the thread from the application or any method will do? I believe pointing at http://stackoverflow.com/q/3590000/1305344 should help to understand `Thread.interrupt` at least. – Jacek Laskowski Mar 11 '13 at 01:21
  • I asked a similar question here http://stackoverflow.com/questions/3489467/killing-an-infinite-loop-in-java and you may find the answers useful – peter.murray.rust Dec 29 '10 at 18:03

6 Answers6

8

The java debugger will allow you to kill a thread by injecting an exception into it.

Start your Java process and have it listen on some port:

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4444 <Your Program>

and connect the debugger with something like:

jdb -attach 127.0.0.1:4444

and issue the following command:

threads

to get a list of the running threads, and use the kill command to kill a running thread.

kill 0xe2e new java.lang.IllegalArgumentException("er");
Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
6

Under this link: http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html:

What if a thread doesn't respond to Thread.interrupt?

In some cases, you can use application specific tricks. For example, if a thread is waiting on a known socket, you can close the socket to cause the thread to return immediately. Unfortunately, there really isn't any technique that works in general. It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt, it wouldn't respond to Thread.stop either. Such cases include deliberate denial-of-service attacks, and I/O operations for which thread.stop and thread.interrupt do not work properly.

jzd
  • 23,473
  • 9
  • 54
  • 76
4

You can't reliably interrupt a thread without cooperation from that thread.

As an ugly hack (not for practical use!), you can substitute System.out and make println throw an exception when interruption condition is met and the thread in question is a current thread (i.e. use it as a hook to provide some cooperation in context of the target thread).

EDIT: Even more elegant option - you can make println interruptable by throwing an exception when Thread.interrupted() is true, so that the thread can be interrupted by calling thread.interrupt().

Semantic of this method would be very close to the ordinary interruptable methods (i.e. methods that throw InterruptedException), although you can't use InterruptedException since it's a checked exception and need to use unchecked RuntimeException instead:

System.setOut(new PrintStream(System.out) {
    public void println(String s) {
        if (Thread.interrupted()) throw new RuntimeException();
        super.println(s);
    }
});
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • Can whoever downvoted this answer provide a reason for the downvote? – Amir Afghani Dec 29 '10 at 18:01
  • 1
    It's what I would do, System.setOut() with your own stream that either closes the stream or throws when you are done. You can even be more precise when you want the thread to exit because you'll be able to process all the text. – Andrew T Finnell Dec 29 '10 at 18:11
  • if you can substitute anything to handle (hook) the calls, you can always check if a threads needs to go by (I throw `ThreadDeath`), you have `Thread.currentThread()` and you can always check a `ThreadLocal` (might need to use `initialValue()`, though) that points to AtomicInteger holding a specific state. I, myself, tend to hook the loggers - they make a perfect and API based target. Interrupt is hard to get passed sometimes due to `try{}catch(Throwable t)` constructs and the flag is lost. – bestsss Feb 12 '11 at 22:42
0

I am not aware of any deprecated method which has been removed from the JRE ever. stop() has been deprecated a very long time, possibly more than 10 years. Its a bad idea to use it, but it may be your best option.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

You can implement the interrupt method using a check variable.

First of all use a volatile check variable as:

volatile boolean tostop = false; // Keep the initial value to be false

Next define your thread to be dependent to this variable.

Thread thread1 = new Thread(){
    public void run() {
        while(!tostop) {
         -- Write your code here --
        }
     }
 }

Next define the function in which to use the thread:

public void ....{
    //Interrupt code
    tostop = true;
    thread1.sleep(300);  // Give the thread sometime for cleanup
    //Use System.exit(0), if the thread is in main function.
}

Hope this helps.

jagbandhuster
  • 677
  • 2
  • 7
  • 20
  • 8
    I thought Dr.Lesh couldn't edit the code! you should probably prefer while (!Thread.currentThread().isInterruptted()) over a check variable too... and sleeping for cleanup? really? – Toby Dec 30 '10 at 13:44
  • 1
    @venomrld If you know your answer us wrong, why not correct it or delete it? – Raedwald May 20 '14 at 19:28
  • bad answer, obviously you can do that if you control thread but if thread is already made or if it is nio fs read then you are screwed with this "answer" – Enerccio Sep 08 '21 at 07:38
0

Ok, I've found the solution and it's really really simple, just sleep the thread and then interrupt it!

final Thread t = getTheThreadToClose();

//Final is important because only in this way you can pass it to the following new Thread

if (t != null && t.isAlive() && !t.isInterrupted()){
    try{
       new Thread(){
           public void run(){
               try{ 
                  t.sleep(3000);//SLEEP INSIDE THE NEW THREAD
               }
               catch(InterruptedException ex){}
           }
       }.start();

       t.interrupt();//INTERRUPT OUTSIDE THE NEW STARTED THREAD
    }
    catch(Exception e){}
}

It works in all cases!

I wanna thank you all for your really useful help, especially venomrld and Toby that gave me inspiration for the solution with their words ;-), and this wonderfoul site that let me ALWAYS solve all my programming problems.

Thank you all again and Happy New Year!

Marco Vasapollo
  • 509
  • 5
  • 16