interrupt one thread inside another thread's run method in Java

匿名 (未验证) 提交于 2019-12-03 09:19:38

问题:

I was reading this post and the suggestions given to interrupt one thread from another is

" " " Here are a couple of approaches that should work, if implemented correctly.

You could have both threads regularly check some common flag variable (e.g. call it stopNow), and arrange that both threads set it when they finish. (The flag variable needs to be volatile ... or properly synchronized.)

You could have both threads regularly call the Thread.isInterrupted() method to see if it has been interrupted. Then each thread needs to call Thread.interrupt() on the other one when it finishes." " "

I do not understand how the second approach is possible that is using Thread.isInterrupted(). That is, how can Thread-1 call Thread.interrupt() on Thread-2.



Consider this example, in the main method I start two threads t1 and t2. I want t1 to stop t2 after reaching certain condition. how can I achieve this?

    class Thread1 extends Thread {           public void run(){             while (!isDone){                 // do something              }         }        //now interrupt Thread-2     }      class Thread2 extends Thread {          public void run(){             try {                      while(!Thread.isInterupted()){                      //do something;                }                catch (InterruptedExecption e){                     //do something                                }        } }       public class test {          public static void main(String[] args){           try {              Thread1 t1 = new Thread1();             Thread2 t2 = new Thread2();             t1.start();             t2.start();         } catch (IOException e) {             e.printStackTrace();         }         }       }

回答1:

The context of this is that you are trying to implement your scheme using thread interrupts.

In order for that to happen, the t1 object needs the reference to the t2 thread object, and then it simply calls t2.interrupt().

There are a variety of ways that t1 could get the reference to t2.

  • It could be passed as a constructor parameter. (You would need to instantiate Thread2 before Thread1 ...)
  • It could be set by calling a setter on Thread1.
  • It could be retrieved from a static variable or array, or a singleton "registry" object of some kind.
  • It could be found by enumerating all of the threads in the ThreadGroup looking for one that matches t2's name.


回答2:

public class test {  private static boolean someCondition = true;   public static void main(String[]args){      Thread t2 = new Thread(new someOtherClass("Hello World"));     Thread t1 = new Thread(new someClass(t2));     t2.start();     t1.start();     try {         t1.join();     } catch (InterruptedException e) {         // TODO Auto-generated catch block         e.printStackTrace();     }  }  static class someClass implements Runnable{      Thread stop;     public someClass(Thread toStop){         stop = toStop;     }       public void run(){         while(true){             try {                 Thread.sleep(500);             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }             if(someCondition && !stop.isInterrupted()){                  stop.interrupt();              }          }     } }  static class someOtherClass implements Runnable{     String messageToPrint;      public someOtherClass(String s){         messageToPrint = s;     }      public void run(){          while(true){             try {                  Thread.sleep(500);               } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }               System.out.println(messageToPrint);         }     } }

}



回答3:

You could consider the use of Future interface. It provides a cancel() method. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html



回答4:

Playing with interruption makes your life unnecessarily hard. Besides the fact that your code must know the threads, interruption does not provide any context information about the reason of the interruption.

If you have a condition that is shared by your code possibly executed by different threads, just encapsulate that condition into an object and share that object:

public class Test {   public static void main(String[] args) {     Condition c=new Condition();     new Thread(new Setter(c)).start();     new Thread(new Getter(c, "getter 1")).start();     // you can simply extend it to more than one getter:     new Thread(new Getter(c, "getter 2")).start();   } } class Getter implements Runnable {   final Condition condition;   final String name;   Getter(Condition c, String n) { condition=c; name=n; }   public void run() {     while(!condition.isSatisfied()) {       System.out.println(name+" doing something else");       try { Thread.sleep(300); } catch(InterruptedException ex){}     }     System.out.println(name+" exiting");   } } class Setter implements Runnable {   final Condition condition;   Setter(Condition c) { condition=c; }   public void run() {     System.out.println("setter: doing my work");     try { Thread.sleep(3000); }     catch(InterruptedException ex){}     System.out.println("setting condition to satisfied");     condition.setSatisfied();   } } class Condition {   private volatile boolean satisfied;    public void setSatisfied() {     satisfied=true;   }   public boolean isSatisfied() {     return satisfied;   } }

The big advantage of this encapsulation is that it is easy to extend. Suppose you want to allow a thread to wait for the condition instead of polling it. Taking the code above it’s easy:

class WaitableCondition extends Condition {   public synchronized boolean await() {     try {       while(!super.isSatisfied()) wait();       return true;     } catch(InterruptedException ex){ return false; }   }   public synchronized void setSatisfied() {     if(!isSatisfied()) {       super.setSatisfied();       notifyAll();     }   } } class Waiter implements Runnable {   final WaitableCondition condition;   final String name;   Waiter(WaitableCondition c, String n) { condition=c; name=n; }   public void run() {     System.out.println(name+": waiting for condition");     boolean b=condition.await();     System.out.println(name+": "+(b? "condition satisfied": "interrupted"));   } }

Without changing the other classes you can now extend your test case:

public class Test {   public static void main(String[] args) {     WaitableCondition c=new WaitableCondition();     new Thread(new Setter(c)).start();     new Thread(new Getter(c, "getter 1")).start();     // you can simply extend it to more than one getter:     new Thread(new Getter(c, "getter 2")).start();     // and you can have waiters     new Thread(new Waiter(c, "waiter 1")).start();     new Thread(new Waiter(c, "waiter 2")).start();   } }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!