在Java中用另一个线程的run方法中断一个线程

我正在阅读这篇文章,并给出了从另一个线程中断一个线程的建议

“”如果正确实施,以下是一些应该有效的方法。

您可以让两个threads定期检查一些常见的标志变量(例如将其命名为stopNow),并安排两个线程在完成时设置它。 (标志变量需要是易失性的……或者是正确同步的。)

您可以让两个threads定期调用Thread.isInterrupted()方法来查看它是否已被中断。 然后每个线程在完成时需要在另一个线程上调用Thread.interrupt()。“”

我不明白第二种方法是如何使用Thread.isInterrupted() 。 也就是说, Thread-1如何在Thread-2上调用Thread.interrupt()



考虑这个例子,在main方法中我启动两个threads t1t2 。 我希望t1在达到某个条件后停止t2 。 我该怎么做到这一点?

  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(); } } } 

这样做的上下文是您尝试使用线程中断实现您的方案。

为了实现这一点, t1对象需要引用t2线程对象,然后它只需调用t2.interrupt()

t1可以通过多种方式获得对t2的引用。

  • 它可以作为构造函数参数传递。 (你需要在Thread1之前实例化Thread2 ……)
  • 它可以通过调用Thread1上的setter来设置。
  • 它可以从静态变量或数组或某种单独的“注册表”对象中检索。
  • 可以通过枚举ThreadGroup中的所有线程来查找与t2名称匹配的线程。
 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); } } } 

}

您可以考虑使用Future接口。 它提供了cancel()方法。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

玩弄中断会让你的生活变得不必要。 除了您的代码必须知道线程这一事实外,中断不会提供有关中断原因的任何上下文信息。

如果您的代码共享的条件可能由不同的线程执行,则只需将该条件封装到对象中并共享该对象:

 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; } } 

这种封装的最大优点是易于扩展。 假设您希望允许线程等待条件而不是轮询它。 使用上面的代码很容易:

 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")); } } 

在不更改其他类的情况下,您现在可以扩展测试用例:

 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(); } }