2011-02-28 59 views
1

我在寫一個簡單的線程應用程序。線程只是一個消息消費者並對其進行處理。但是,如果線程以某種方式被打斷並且消息沒有完全處理,我想把它放回隊列並讓其他實例獲取它。因此,我不得不像這樣的代碼:在運行()的同步塊的中間是否可以中斷線程?

public void run() 
{ 
    Map<String, String> data = null; 
    try 
    { 
     while(true) 
     { 
      data = q.getData(); 
      System.out.println(this+" Processing data: "+data); 
      // let others process some data :) 
      synchronized(this){ 
       sendEmail(data); 
       data = null; 
      } 
     } 
    } 
    catch (InterruptedException e) 
    { 
     System.out.println(this+" thread is shuting down..."); 
     if(null!=data) 
      q.add(data); 
    } 

} 

謝謝...

編輯:感謝您的答覆。現在一切都很清楚。我明白,即使代碼行在同步塊中,如果它們中的任何一個都可以拋出InterruptedException,那麼它只是意味着它們可以在此時被中斷。 q.getData()行將此線程置於'阻塞'狀態(我在q.getData()中使用LinkedBlockedQueue)。那時,這個線程可以被中斷。

+0

這是壞的...我做了一個快速測試,我可以在同步塊中間中斷線程......壞的不好...... – demotics2002 2011-02-28 08:09:27

+0

爲什麼在這種情況下需要'synchronized'? – axtavt 2011-02-28 08:23:43

+0

我想將sendMail()和設置爲null爲原子。 – demotics2002 2011-02-28 08:29:03

回答

4

除了大衛·哈克尼斯的回答:你也不明白​​關鍵字的含義。

Synchornized不是一種「原子」或「不可中斷」塊。

除了其他線程不能同時在同一個對象上輸入同步塊(在你的情況下爲this)(+某些內存一致性保證與你的情況無關),同步塊不能提供任何保證。

因此你的情況的synchornized使用是沒有意義的,因爲沒有必要保護data從其他線程(也,你是同步的this的併發訪問,我不認爲其他線程將同一對象上同步)。

參見:

+0

感謝您的光。我現在明白了。 – demotics2002 2011-02-28 08:50:39

0

Java同步是指當一個線程已經收購了它沒有其他的線程可以訪問相同的鎖。

如果您不希望任何其他線程能夠訪問消息(或任何其他對象),請使用synchronized(message)塊。

+0

'是'部分是正確的。但奇怪的是我的另一個線程在同步塊內部時能夠中斷這個線程。 – demotics2002 2011-02-28 08:26:51

+0

在你的代碼中,你使用'synchronized(this){}'來獲取線程上的鎖。你想要的是鎖定消息,所以你需要使用'synchronized(data){}' – 2011-02-28 08:57:19

6

其他線程在其上調用interrupt()時線程不會捕獲InterruptedException,也不會奇蹟般地停止它的任何操作。相反,該方法設置一個標誌,線程可以使用interrupted()讀取。如果設置了某些其他方法,則會檢查此標誌並提高InterruptedException。例如,Thread.sleep()和許多等待外部資源的I/O操作都會拋出它。

查看Java Thread Interrupts Tutorial瞭解更多信息。

+0

我不明白。我有另一個線程(僅用於測試),可以在sendMail()和data = null中間中斷此線程,這些線程位於同步塊中。 – demotics2002 2011-02-28 08:32:43

+0

@demotics - 哦,我明白了。你認爲'synchronized'可以讓你的線程保持JVM的全部注意力,而無需安排任何其他線程運行(你稱之爲中斷)。正如axtavt指出的那樣,這不是'synchronized'所做的事情,也不是線程中斷的意思。 – 2011-02-28 22:13:16

+0

謝謝大衛。我最初並不瞭解你的觀點。但現在很清楚。你的回答很大程度上幫助我意識到我對線程的理解太缺乏。 – demotics2002 2011-03-01 01:42:05

1

忽略該while(true)使線程進入一個CPU循環的那一刻...

如果sendMail做任何檢查線程中斷它會拋出一箇中斷的異常。所以你的問題的答案可能是堅實的,線程可以在同步塊內被中斷,你將不得不捕捉異常並檢查。

這就是說,InterruptedException是一個檢查異常,所以缺少有趣的bugger在較低級別完成,sendMail應該指出它可以拋出InterruptedException。