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