2010-08-05 150 views
2

我知道這是不適當的建議,但我仍然試圖尋找一種方法來中斷掛起的線程,從另一個線程是保持時間。如何從監視器中斷另一個線程線程

我所做的是: 我在即將發生可疑的網絡操作之前​​啓動監視器線程。該線程應該監視自啓動以來的時間,如果時間超過某個閾值,它會殺死最初啓動它的線程。爲了通知這個新線程,要殺死哪個線程,新線程的對象被傳遞給要被監視的線程對象。

簡單地說,這是發生了什麼:

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

回答

-1

如果您問我,這實際上是正常行爲。如果你打斷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

1

檢查在調用時是否得到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

2

我認爲你的代碼有問題(除非我沒有明確你的規格)。下面的代碼運行正常(對不起,可怕的嵌套結構):

產量爲:

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 ,不知何故,你沒有注意到它?

1

另一種可能性是,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; 
}