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

时间:2014-03-04 19:49:21

标签: java multithreading interrupt

我正在阅读此post,并且建议从另一个线程中断一个线程

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

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

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

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



考虑这个例子,在主要方法中,我开始两个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();
        }
        }


    }

4 个答案:

答案 0 :(得分: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);
        }
    }
}

}

答案 1 :(得分:2)

这样做的背景是你试图使用线程中断来实现你的方案。

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

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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

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