简体   繁体   English

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

[英]interrupt one thread inside another thread's run method in Java

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 (eg call it stopNow), and arrange that both threads set it when they finish. 您可以让两个threads定期检查一些公共标志变量(例如,将其称为stopNow),并安排两个线程在完成时对其进行设置。 (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. 您可以让两个threads定期调用Thread.isInterrupted()方法以查看其是否已被中断。 Then each thread needs to call Thread.interrupt() on the other one when it finishes." " " 然后,每个线程在完成时都需要在另一个线程上调用Thread.interrupt()。

I do not understand how the second approach is possible that is using Thread.isInterrupted() . 我不明白使用Thread.isInterrupted()的第二种方法怎么可能。 That is, how can Thread-1 call Thread.interrupt() on Thread-2 . 也就是说, Thread-1如何在Thread-2上调用Thread.interrupt()



Consider this example, in the main method I start two threads t1 and t2 . 考虑这个示例,在main方法中,我启动了两个threads t1t2 I want t1 to stop t2 after reaching certain condition. 我希望t1在达到特定条件后停止t2 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();
        }
        }


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

} }

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() . 为了实现这一点, t1对象需要引用t2线程对象,然后只需调用t2.interrupt()

There are a variety of ways that t1 could get the reference to t2 . t1可以通过多种方式获得对t2的引用。

  • It could be passed as a constructor parameter. 它可以作为构造函数参数传递。 (You would need to instantiate Thread2 before Thread1 ...) (您需要在Thread1之前实例化Thread2 ...)
  • It could be set by calling a setter on Thread1. 可以通过在Thread1上调用setter进行设置。
  • 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. 可以通过枚举ThreadGroup中的所有线程来寻找与t2名称匹配的线程来找到它。

You could consider the use of Future interface. 您可以考虑使用Future接口。 It provides a cancel() method. 它提供了一个cancel()方法。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM