Java 如何从监视器线程中断另一个线程

Java 如何从监视器线程中断另一个线程,java,multithreading,interrupt,Java,Multithreading,Interrupt,我知道这是不明智的,但我仍在试图寻找一种方法,从另一个保持时间的线程中断一个挂起的线程 我所做的是: 我在有问题的网络操作即将发生之前启动了监视器线程。这个线程应该监视自启动以来经过的时间,如果时间超过某个阈值,它将终止最初启动它的线程。为了通知这个新线程要终止哪个线程,新线程的对象被传递给要监视的线程的对象 简言之,情况就是这样: A创建B,B创建C,B告诉C它自己,C保留时间,如果时间过期C杀死B(我在B的run方法中使用“currentThread()”将细节传递给C,并且我已经确认确实传

我知道这是不明智的,但我仍在试图寻找一种方法,从另一个保持时间的线程中断一个挂起的线程

我所做的是: 我在有问题的网络操作即将发生之前启动了监视器线程。这个线程应该监视自启动以来经过的时间,如果时间超过某个阈值,它将终止最初启动它的线程。为了通知这个新线程要终止哪个线程,新线程的对象被传递给要监视的线程的对象

简言之,情况就是这样:

A创建B,B创建C,B告诉C它自己,C保留时间,如果时间过期C杀死B(我在B的run方法中使用“currentThread()”将细节传递给C,并且我已经确认确实传递了正确的对象)

现在的问题是,由于某种原因,对B.interrupt()的调用正在扼杀C本身


[注意:大写字母表示线程名称]

如果你问我,这实际上是正常的行为。如果中断B,它将被垃圾收集。因为对C的唯一引用也是GC'd,所以它将不再存在/运行


最好的办法是确保有一个线程管理线程B和C(并将线程C注入线程B)。这样,总是有一个对线程C的引用,它可能会杀死线程B。(但在管理线程中使用线程B时必须小心)

在调用
B.interrupt()时检查是否得到
SecurityException
。另外,您确定您的
B.interrupt()
不会简单地返回并且线程C成功完成吗?基于,看起来线程C调用
B.interrupt()
将设置线程B的中断状态并完成运行。我认为线程B在您的情况下不会出现任何异常,除非它满足特殊要求(例如,等待监视器、等待中断频道等)。

我认为您的代码有问题(除非我没有正确理解您的规范)。下面的代码按预期运行(对于可怕的嵌套结构感到抱歉):

产出为:

C is about to interrupt B
B is interrupted
C is still alive... is B alive yet?false
代码是:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;


public class Scrap {
    public static void main(String[] args) {
        Thread A = new Thread() {
            @Override
            public void run() {
                Thread B = new Thread() {
                    @Override
                    public void run() {
                        final CountDownLatch latch = new CountDownLatch(1);
                        final AtomicReference<Thread> pointer = new AtomicReference<Thread>();
                        Thread C = new Thread() {
                            @Override
                            public void run() {
                                try {
                                    //wait for B to be ready
                                    latch.await();
                                    Thread.sleep(2000);
                                    System.out.println("C is about to interrupt B");
                                    pointer.get().interrupt();
                                    Thread.sleep(2000);
                                    System.out.println("C is still alive... is B alive yet? " + pointer.get().isAlive());

                                } catch (InterruptedException e) {
                                    System.out.println("C interrupted");
                                    return;
                                }
                            }
                        };//C
                        C.start();
                        latch.countDown();
                        //Not sure how you did it, so just going with this:
                        pointer.set(Thread.currentThread());


                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            System.out.println("B is interrupted");
                            return;
                        }
                        System.out.println("B survived");

                    }
                };//B
                B.start();
            }
        };
        A.start();
    }
}
import java.util.concurrent.CountDownLatch;
导入java.util.concurrent.AtomicReference;
公共类废料{
公共静态void main(字符串[]args){
线程A=新线程(){
@凌驾
公开募捐{
线程B=新线程(){
@凌驾
公开募捐{
最终倒计时闩锁=新倒计时闩锁(1);
最终AtomicReference指针=新的AtomicReference();
线程C=新线程(){
@凌驾
公开募捐{
试一试{
//等待B准备好
satch.wait();
《睡眠》(2000年);
System.out.println(“C即将中断B”);
指针.get().interrupt();
《睡眠》(2000年);
System.out.println(“C还活着……B还活着吗?”+pointer.get().isAlive());
}捕捉(中断异常e){
系统输出打印项次(“C中断”);
返回;
}
}
};//C
C.开始();
倒计时();
//我不知道你是怎么做到的,所以就这么说吧:
set(Thread.currentThread());
试一试{
睡眠(5000);
}捕捉(中断异常e){
System.out.println(“B中断”);
返回;
}
系统输出打印项次(“B生存”);
}
};//B
B.开始();
}
};
A.开始();
}
}

我的猜测是线程间的可见性。在上面的代码中,我使用原子引用来确保可见性。如果您没有这样做,那么您传递线程B的引用(“s值”)的任何字段都可能对C不可见。然后,当C尝试中断此线程对象时,它会看到null,中断会导致NullPointerExceptin,而不知何故您没有注意到它?

另一种可能性是,C成功中断并返回,但B对此没有响应。这是很有可能的,因为只有当B被相应地编码时,中断才有效

有两种方法可以对中断做出反应。
1.检查中断标志(通常在需要较长时间的操作之前)

2.根据中断例外情况采取行动

catch(InterruptedException e){
    log.info("Cancel Requested");

    //Preserve interrupted status.
    //If this class is the owner of the thread,
    //Not necessary.
    Thread.currentThread().interrupt(); 

    return;
}

C死亡的原因是什么?有线索吗?你确定它死了吗?您可以发布监控线程的代码吗?这里有一个指向监视器代码的链接,“沙漏”只是我创建的一个小计时器类,在构造函数中,你可以在几秒钟内通过一个超时,然后你可以启动、停止或检查任务的完成情况。评论继续:我看不到C死亡的任何原因,没有报告错误,所以我不能给你任何堆栈跟踪。我确信当我用eclipse实时观看线程执行时,它会消失,只要执行了必要的语句,线程C就会消失。在这一点上,如果你不发布任何代码,没有人能够帮助你。我确实发布了代码,我不知道如何获得代码格式,所以,我
catch(InterruptedException e){
    log.info("Cancel Requested");

    //Preserve interrupted status.
    //If this class is the owner of the thread,
    //Not necessary.
    Thread.currentThread().interrupt(); 

    return;
}