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

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

问题描述:

我知道这是不适当的建议,但我仍然试图寻找一种方法来中断挂起的线程,从另一个线程是保持时间。如何从监视器中断另一个线程线程

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

简单地说,这是发生了什么:

A创建B,B创建C,B告诉C约本身,C保持时间,如果时间过期Ç杀死B(我传递的细节到C后B的运行方法使用“currentThread()”,并且我已经确认正确的对象确实正在通过)

现在,问题在于,由于某种原因,此操作不起作用,因此调用B.interrupt )正在杀死C本身。

[注意:大写字母表示螺纹名称]

+0

什么是C到死的原因(通常是需要很长时间的操作之前)?任何堆栈跟踪?你知道它肯定会死吗?你能发布你的监控线程的代码吗? – 2010-08-05 07:02:35

+0

http://pastebin.com/JVfpkqEg这里是监视器代码的链接,“Hourglass”只是我制作的一个小型定时器类,在构造函数中你可以在几秒钟内超时,然后你就可以开始,停止或检查任务是否完成。 – angryInsomniac 2010-08-05 09:02:42

+0

评论继续:我没有看到C死亡的任何理由,没有错误报告,所以我不能给你任何堆栈跟踪。 我确信它死了,因为我在eclipse中实时观察线程执行,只要执行必要的语句,线程C就会死掉。 – angryInsomniac 2010-08-05 09:14:33

如果您问我,这实际上是正常行为。如果你打断B,它将被垃圾收集。由于对C的唯一引用也是GC'd,它将停止存在/运行。

最好的想法可能是确保有一个线程管理线程B和C(并将线程C插入线程B)。这样,总是有一个线程C的引用,它可以杀死线程B.(但是你必须小心你在管理线程中使用线程B做什么)

+0

其实,那是我相信,但是,我观察到的是,C被破坏,B继续存在。 – angryInsomniac 2010-08-05 07:04:58

+0

我认为线程有来自ThreadGroup对象的引用。在这个例子中,我不会线程C是CG'd – 2010-08-05 07:06:29

+0

是的,线程不是那样的GCd。 – 2010-08-05 08:15:29

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

+0

据我所见,代码中任何地方都不会抛出任何异常 – angryInsomniac 2010-08-05 08:24:30

+0

您可以发布您的监控线程的代码吗? – 2010-08-05 08:38:51

我认为你的代码有问题(除非我没有明确你的规格)。下面的代码运行正常(对不起,可怕的嵌套结构):

产量为:

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

我的(野生)的猜测是线程间的能见度。在上面的代码中,我使用原子引用来确保可见性。如果你没有这样做,可能无论你传递线程B的引用(的值)的任何字段可能对C而言都是不可见的。然后,当C尝试中断这个线程对象时,它看到null,并且中断导致NullPointerExceptin ,不知何故,你没有注意到它?

另一种可能性是,C中断成功并返回,但B不响应。这是很有可能的,因为如果B被相应地编码,中断只会起作用。

有2种方式来应对中断。
1。检查中断标志

if(Thread.currentThread().isInterrupted()){ 
    log.info("Cancel requested"); 
    return; 
} 
someStuffThatTakesLongTimeToExecute(); 

2.Act对中断例外

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