【问题标题】:Assertion error polling from inside a new thread in ZeroMQ (JeroMQ)从 ZeroMQ (JeroMQ) 中的新线程内部轮询断言错误
【发布时间】:2023-04-05 01:08:01
【问题描述】:

我的代码如下所示:

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)

我正在使用带有 JeroMQ 0.3.5-SNAPSHOT 的 Java 8

【问题讨论】:

    标签: java zeromq jeromq


    【解决方案1】:

    ZMQ 套接字不是线程安全的。您在一个线程中创建套接字然后在另一个线程中使用它的能力有限,但我猜测看不见的代码将分支成多个线程,所有线程都试图同时使用套接字。这是 ZMQ 的禁忌。通常,您应该在将要使用它们的线程中创建套接字。

    ZMQ 上下文线程安全的。

    【讨论】:

    • 这些尝试都是连续的,但我想这可能是一个问题。我将有多个客户端通过 tcp 向服务器发送消息,但服务器上没有多个线程直接写入套接字。问题是我需要在请求/回复层之上的服务器管理层,并且当套接字处于轮询循环中时不能拥有服务器管理代码块。如果不在单独的线程中启动套接字,我看不到这样做的方法。
    • ZMQ 创始人的话是,在将套接字从一个线程移交给另一个线程时,您必须在线程之间执行完整的内存屏障,并且一次只能有一个线程可以“拥有”一个套接字。如果您想要一个完全专用于接收和/或发送消息的线程,您通常会在该线程和主线程之间创建第二个套接字对。第一个线程充当代理,您的主线程只是以非阻塞方式定期检查新消息。
    猜你喜欢
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多