0

Scenario: I have a limited number of independent tasks which will be given to few threads to finish those tasks. The main thread should wait for all the threads to finish their tasks. While it works for most of the time, sometimes one of the threads can't finish its tasks and so the main thread waits indefinitely. How is it possible to kill that blocked thread?

Here is the sample code which explains the scenario.

Client Class

public class ThreadStop {

public static void main(String[] args){

    List<Thread> threadList = getMyThreadList();        

    for (Thread thread : threadList) {
        thread.start();
    }

    System.out.println("Waiting for Child Threads to die");

    for (Thread thread : threadList) {
        try {
            thread.join();
            System.out.println(thread.getName() + " Finished its job");             
        } catch (InterruptedException e) {
            System.out.println("Interrupted Exception thrown by : "
                    + thread.getName());                
        }
    }

    System.out.println("All Child Threads Finished their Job");
}

private static List<Thread> getMyThreadList() {
    List<Thread> threadList = new ArrayList<>();
    MyThread myThread;
    Thread thread;
    for(int i=0; i<10; i++){
        myThread = new MyThread();
        thread = new Thread(myThread);
        thread.setName("Thread "+i);
        threadList.add(thread);
    }
    return threadList;
}
}  

Thread class

public class MyThread implements Runnable{

@Override
public void run() {
    System.out.println("hello world by thread "+      Thread.currentThread().getName());        
}

}

Note Please note that I can't use executor framework.

real gadha
  • 123
  • 1
  • 12
  • 1
    *I can't use executor framework*: why? And why is the task never finishing? Is it blocked waitin gfor input? Is it stuck in an infinite loop? That's important: if it's a bug, it should be fixed. If it's blocked waiting, then you should be able to interrupt it. Show us what the blocked task is doing. – JB Nizet Nov 01 '15 at 14:06
  • @JBNizet I can't use executor framework because its part of existing code base which is not using the framework. If we have to use it, it will be lots of refactoring. The blocked task make a network call and sometimes it seems just hangs. – real gadha Nov 01 '15 at 14:17
  • One way would be to use a volatile boolean value that indicates whether a thread should continue running or it should halt. The main thread can set the value of the boolean appropriately. Another suggestion is to interrupt the blocking thread and do clean up and exit logic when you catch the Interrupted exception. Of course this will not work if there's infinite loop or some other bug in the thread's code. – turingcomplete Nov 01 '15 at 14:28
  • 2
    Your example does not explain your problem ... because the threads won't block for an appreciable length of time. – Stephen C Nov 01 '15 at 14:29
  • 3
    @turingcomplete interrupting a thread is the same thing as setting a boolean value. The difference is that it will also make most blocking methods stop by throwing an exception. My point is that using a separate boolean value is most of the time a bad idea. That's the role of the interrupt flag. – JB Nizet Nov 01 '15 at 14:31
  • Possible duplicate of [How to stop a java thread gracefully?](http://stackoverflow.com/questions/3194545/how-to-stop-a-java-thread-gracefully) – Sneftel Nov 01 '15 at 14:33
  • @JBNizet I am convinced. I think interrupting is a better way. – turingcomplete Nov 01 '15 at 14:34
  • @StephenC In the actual code the task has hundreds of code. As its not possible to provide the real code, I have provided a dummy thread. – real gadha Nov 01 '15 at 14:50
  • 1
    Well, it at least needs to block in a way that is characteristic of the actual code. Otherwise we can't tell you how to solve the problem. – Stephen C Nov 01 '15 at 15:00

1 Answers1

0

If the tasks are explicitly written as subclassing Thread directly, then using the Executor framework is out[1]. In that case you should use join() with a timeout value. If the join does not succeed, you can interrupt() the thread (but that's not a guaranteed 'kill'). Poking threads directly is not a nice way of doing things -- it's like a game in which you always lose, the only winning move is not to play.

However if the tasks are written slightly more sanely/with benefit of modern insights, they will be something that can at least be wrapped a Runnable (or indeed, they are Runnable and just passed to a constructor of Thread). At which point you can use the Executor framework again.

  1. Although you could pass the instances of Thread to an Executor directly, provided that you can avoid calling start() or run() the Threads elsewhere in the code (because if the other code also executes the same task, then the task is executed twice in a best-case scenario).
user268396
  • 11,576
  • 2
  • 31
  • 26
  • Hmm. Thread implements Runnable. You can pass a Thread to an Executor. Not the best way to design the code, but it's correct. – JB Nizet Nov 01 '15 at 14:39
  • @JBNizet added your observation, do note: it won't work properly if other code 'manually' calls `start()` or `run()` on the threads because then (best case scenario) the same task is executed twice. – user268396 Nov 01 '15 at 14:47
  • If `t.interrupt()` is going to work, then why start with the `t.join(timeout)` call? Why not interrupt all of the threads right off the bat? – Solomon Slow Nov 02 '15 at 14:34
  • @jameslarge because you don't want to. You want to let the threads run and hope the work is completed within some specified max timeout value. Once you `interrupt()` and that works, it means whatever work that thread was doing is probably toast -- it forcibly breaks wait/notify locks and such. You only want to kill the work if it appears to be stalled. – user268396 Nov 04 '15 at 21:51