2015-06-03 129 views
2

我的代碼看起來像這樣:斷言錯誤輪詢

public void handleRequests() { 
    ZMQ.Poller items = new ZMQ.Poller(1); 
    items.register(clientEndpoint, ZMQ.Poller.POLLIN); 
    while (!Thread.currentThread().isInterrupted()) { 
     byte[] message; 
     items.poll(); // this is the line that throws exception. 
     if (items.pollin(0)) { 
      message = clientEndpoint.recv(0); 
     } 
    } 
} 

它工作正常,當我直接調用它:

foo.handleRequests(); 

但它失敗定期的斷言錯誤,如果它是運行在一個新的線程:

final Runnable listener = worldviewServer::handleRequests; 
Executors.newSingleThreadExecutor().execute(listener); 

堆棧跟蹤我得到如下圖所示:

Exception in thread "pool-6-thread-1" java.lang.AssertionError 
at zmq.Mailbox.recv(Mailbox.java:113) 
at zmq.SocketBase.process_commands(SocketBase.java:820) 
at zmq.SocketBase.getsockopt(SocketBase.java:258) 
at zmq.PollItem.readyOps(PollItem.java:107) 
at zmq.ZMQ.zmq_poll(ZMQ.java:708) 
at zmq.ZMQ.zmq_poll(ZMQ.java:600) 
at org.zeromq.ZMQ$Poller.poll(ZMQ.java:1618) 
at org.zeromq.ZMQ$Poller.poll(ZMQ.java:1592) 
at com.tracelink.worldview.server.Head.handleRequests(Head.java:68) 
at com.tracelink.worldview.server.WorldviewServer.handleRequests(WorldviewServer.java:236) 
at com.tracelink.worldview.server.fsm.EnablingAction$$Lambda$12/404648734.run(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 

我使用Java 8 JeroMQ 0.3.5-SNAPSHOT

回答

0

ZMQ套接字不是線程安全的。你在一個線程中創建一個套接字的能力有限,然後在另一個線程中使用它,但我猜測,看不見的代碼將分支到多個線程,所有嘗試同時使用套接字的線程。這是一個ZMQ no-no。通常,您應該在要使用的線程中創建套接字。

ZMQ上下文線程安全。

+0

這些嘗試都是連續的,但我認爲這可能是一個問題。我會讓多個客戶端通過tcp向服務器發送消息,但是服務器上沒有多個線程直接寫入套接字。問題是我需要req/reply層之上的一個服務器管理層,並且在套接字處於輪詢循環時不能擁有服務器管理代碼塊。如果沒有在單獨的線程中啓動套接字,我沒有辦法做到這一點。 –

+0

ZMQ創始人的話是,當將套接字從一個線程切換到另一個線程時,您必須在線程之間執行完整的內存屏障,並且一次只有一個線程可以「擁有」套接字。如果您希望完全致力於接收和/或發送消息的線程在該線程和主線程之間創建第二個套接字對,您通常會執行什麼操作。第一個線程充當代理,並且您的主線程僅以非阻塞的方式定期檢查新消息。 – Jason