2016-04-15 92 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