2016-04-15 91 views
0

我正在使用「收發器」將請求從客戶端發送到服務器並等待響應。我是從[這裏]學會[1]的方式來兩個線程之間的溝通,並寫了波紋管代碼:Java:等待線程異常通知

public class ThreadEvent { 

    private Object lock; 
    private Object data; 
    private String ntfInfo; 

    public ThreadEvent() { 
     data = null; 
     lock = new Object(); 
     ntfInfo = "NONE"; 
    } 

    public boolean await(int time) { 
     synchronized (lock) { 
      try { 
       lock.wait(time); 
       return true; 
      } catch (InterruptedException ex) { 
       LogManager.ex(ex); 
       return false; 
      } 
     } 
    } 

    public void signal() { 
     synchronized (lock) { 
      ntfInfo = (new Throwable()).getStackTrace()[1].getMethodName() + "@" 
        + (new Throwable()).getStackTrace()[1].getClassName() + "@" 
        + "line" + (new Throwable()).getStackTrace()[1].getLineNumber() + "@" 
        + (new Throwable()).getStackTrace()[1].getFileName(); 
      lock.notify(); 
     } 
    } 

    public synchronized void putData(Object data) { 
     this.data = data; 
    } 

    public synchronized Object takeData() { 
      Object res = data; 
      data = null; 
      return res; 
    } 

    public String takeNtfInfo() { 
     String info = ntfInfo; 
     ntfInfo = "NONE"; 
     return info; 
    } 
} 

我發現有時候發送和等待線程並不總是被響應通知,也沒有被打斷,(按照我的理解),但是被一些神祕的「東西」等待了。這裏是日誌:

1460717223039:DEBUG:1 starting... @<init>@[email protected]@GUIManager.java 
1460717229475:DEBUG:2 transceive()@[email protected] 
1460717229735:DEBUG:3 forward()@[email protected] 
1460717229739:DEBUG:4 transceive(ivoked by: [email protected]@[email protected])@[email protected] 
1460717229750:DEBUG:5 transceive()@[email protected] 
1460717229768:DEBUG:6 forward()@[email protected] 
1460717229768:DEBUG:7 transceive(ivoked by: [email protected]@[email protected])@[email protected] 
1460717229770:DEBUG:8 transceive()@[email protected] 
1460717234771:DEBUG:9 transceive(ivoked by: NONE)@[email protected] 

您可能會看到LINE2/3/4是一個事務,LINE5/6/7是另一個交易,但line8/9示出了該問題。如果收發器被某人喚醒,它應該打印該線程的名稱,或者如果它被中斷,它應該通過LogManager.ex(ex)打印異常堆棧。但事實並非如此。我做錯了什麼?

+0

服務器也在我的電腦上,所以你可以看到響應時間很短。但是日誌行8/9顯示收發器()立即被喚醒,這是不正常的事情。 – howToDeleteMyAccount

+0

關於這個話題在這裏有一個冗長的討論:http://stackoverflow.com/questions/1050592/do-spurious-wakeups-actually-happen – NAMS

回答

0

當您撥打notify()時,只會通知正在等待的線程。如果線程正在做其他事情,通知就會丟失。

當您致電wait()時,它可能會虛假地喚醒。

總之;

  • 只有在狀態改變後纔會通知。
  • 只能在一個while循環中等待,等待之前檢查狀態檢查。
+0

我的問題是等待線程WSTransceiver.transceive(DataPackage包)有時被喚醒而不是來自WSTransceiver.forward(DataPackage包)的通知,而是通過「其他」。您看到我在ThreadEvent.signal()中的通知程序/調用者的信息上添加了一條軌跡,但沒有收到任何信息。 – howToDeleteMyAccount

+1

我終於可以認識到,1460717234771(日誌line9)和1460717229770(日誌line8)之間的區別實際上是5秒,所以這是由於在同一鏈接中正在進行的文件傳輸導致的網絡超時。所以這是解決的,這裏沒有什麼神祕的。 – howToDeleteMyAccount