1

Suppose I have following piece of code running by a thread:

public void logic()
{
   //Step1
   //Step2
   //Step3
   //Step4
   ...
   ...
   //Stepn
}

Nowhere in this method the interruptible methods are called(like wait, sleep, join).And some steps are taking lot of times to execute. The reason might be anything other than blocking operations like (socket.read or read methods of file). And I want to ensure that if the entire logic method is not executed in say M seconds then the thread should be killed. What is the best way to achieve this?

Mac
  • 1,711
  • 3
  • 12
  • 26
  • 2
    Look at this question, the answers might help you: http://stackoverflow.com/questions/2275443/how-to-timeout-a-thread – Tom Sep 21 '14 at 21:51
  • Have you seen this: https://stackoverflow.com/questions/2275443/how-to-timeout-a-thread? – Abrixas2 Sep 21 '14 at 21:52
  • @Tom that will work only if the underlying code is made to handle or generate interrubtible exceptions. But here, it is not the case. – Mac Sep 21 '14 at 21:54
  • 2
    @Mac Unless you put code like `this.interrupted()` into defined points of `logic`, according to the aforementioned question, there is no portable way to reliably kill the thread. But theoretically you could run `logic` in another process and use the operating system to kill that process, if it takes too long. – Abrixas2 Sep 21 '14 at 22:03
  • 2
    Without interrupted exceptions, it is not possible to stop a thread at all without stopping its process. – Alexander Jardim Sep 21 '14 at 22:23

3 Answers3

1

In general stopping a thread without cooperation of the running thread itself is a "messy" thing to do. (Read up on why Java's Thread.stop() is deprecated). Also Posix threads lack a thread kill mechanism).

What you probably want is a "request stop" state. The thread periodically polls this to see if it should shut itself down. If told to shut down it knows how to clean up after itself.

seand
  • 5,168
  • 1
  • 24
  • 37
1

You say that "nowhere in this method the interruptible methods are called(like wait, sleep, join)", but interruption isn't limited to blocking methods; any method can respond to interruption if you check for it.

Put something like this between each step in your logic method:

if (Thread.currentThread().interrupted()) {
    throw new InterruptedException();
}

(You might want to actually put this into a static allowInterruption method somewhere and just call that after each step.)

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • Thanks , So according to you there is no other way of stopping the thread while it is executing the dirty code without altering my logic method ? – Mac Sep 22 '14 at 03:11
  • 1
    Well, you can't (safely) just force a thread to stop. You have to notify it that it *should* stop, and let it do so on its own. You could use a flag of your own for that purpose (i.e. a `volatile boolean` variable), but every thread already has an interrupt flag so you might as well just use that. – Wyzard Sep 22 '14 at 03:18
  • If the thread lingers longer on random steps in logic method on each execution then to give it a real time effect of cancellation do I need to check for Thread.currentThread().interrupt() after every step? – Mac Sep 22 '14 at 03:22
  • 1
    Check for interruption in as many places as necessary to ensure that the thread notices the interrupt in a timely manner. That might mean putting interruption checks between the sub-steps of one of the "main" steps, for example. – Wyzard Sep 22 '14 at 03:26
  • Hmm.. going by the comments and answer I feel deforming or assassinating my method logic lolzzz.. Thanks for your answer.. But please update your answer in case you find any other better way of doing that ;) – Mac Sep 22 '14 at 03:38
  • 1
    You might want to read [this article](http://www.ibm.com/developerworks/library/j-jtp05236/) on working with thread interruption, particularly the section titled "implementing cancelable tasks". – Wyzard Sep 22 '14 at 03:40
0

I would use a timed join. At the end of the timeout, you can just interrupt your thread executing the logic, which may cause an InterruptedException. Of course, you should comply with the Java monitor specification, so you need some checks on the interrupted state in your logic thread.

If you really cannot have interrupted checks, then you may want to use a Future:

Runnable job = new MyRunnable();  
    ExecutorService executor = Executors.newSingleThreadExecutor();  
    final Future future = executor.submit(job);  

    try {  
        // Execute the job with a time limit  
        future.get(5000, TimeUnit.MILLISECONDS);  

    } catch (final TimeoutException e) {  

        // Operation timed out, so log it and attempt to cancel the thread 
        // Notice that the thread is not going to be killed!
        future.cancel(true);                  

    } finally {  
    executor.shutdownNow();

}

Just replace the Runnable job with your logic thread. Source for the code: http://www.coderanch.com/t/234096/threads/java/executing-time-bounded-job

Manu
  • 4,019
  • 8
  • 50
  • 94
  • 1
    I know this. But please re-read the question. It is clearly specified that there is no checks for interrupted state in the logic method. – Mac Sep 21 '14 at 22:20
  • First of all this code will cancel the job only if the job contains code to check interrupted states.. Second, above code will not kill the thread. – Mac Sep 21 '14 at 22:29
  • This is as far as you can go without recurring to OS services (at the best of my knowledge). Anything beyond this is not something contemplated by the Java Specification. I would suggest refactoring the design, if possible. – Manu Sep 21 '14 at 22:37
  • Please mention in your answer that calling future.cance(true) doesn't kill the thread. So that I can +1 your answer and OPs can get to know the correct functionality while going thorough this link.. – Mac Sep 22 '14 at 03:39