JeroMQ正确关闭

Seb*_*cht 7 sockets recv zeromq jeromq

我想知道如何正确关闭JeroMQ,到目前为止我知道三种方法都有它们的优点和缺点,我不知道哪一个是最好的.

情况:

  • 线程A:拥有上下文,应提供启动/停止方法
  • 线程B:实际的侦听器线程

我目前的方法:

线程A.

static ZContext CONTEXT = new ZContext();
Thread thread;

public void start() {
    thread = new Thread(new B()).start();
}

public void stop() {
    thread.stopping = true;
    thread.join();
}
Run Code Online (Sandbox Code Playgroud)

线程B.

boolean stopping = false;
ZMQ.Socket socket;

public void run() {
    socket = CONTEXT.createSocket(ROUTER);
    ... // socket setup
    socket.setReceiveTimeout(10);

    while (!stopping) {
        socket.recv();
    }

    if (NUM_SOCKETS >= 1) {
        CONTEXT.destroySocket(socket);
    } else {
        CONTEXT.destroy();
    }
}
Run Code Online (Sandbox Code Playgroud)

这很有用.关机10ms对我来说没有问题,但是当没有收到消息时,我会不必要地增加CPU负载.目前我更喜欢这个.


第二种方法在两个线程之间共享套接字:

线程A.

static ZContext CONTEXT = new ZContext();
ZMQ.Socket socket;
Thread thread;

public void start() {
    socket = CONTEXT.createSocket(ROUTER);
    ... // socket setup
    thread = new Thread(new B(socket)).start();
}

public void stop() {
    thread.stopping = true;
    CONTEXT.destroySocket(socket);
}
Run Code Online (Sandbox Code Playgroud)

线程B.

boolean stopping = false;
ZMQ.Socket socket;

public void run() {
    try {
        while (!stopping) {
            socket.recv();
        }
    } catch (ClosedSelection) {
        // socket closed by A
        socket = null;
    }
    if (socket != null) {
        // close socket myself
        if (NUM_SOCKETS >= 1) {
            CONTEXT.destroySocket(socket);
        } else {
            CONTEXT.destroy();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

像魅力一样工作,但即使recv已经阻止异常也不会被抛出.如果我在启动线程A后等待一毫秒,则始终抛出异常.我不知道这是一个错误还是仅仅是我滥用的影响,因为我共享套接字.


"revite"之前问了这个问题(https://github.com/zeromq/jeromq/issues/116)并得到了第三个解决方案的答案:https: //github.com/zeromq/jeromq/blob/master/的src /测试/ JAVA /导向/ interrupt.java

简介:他们调用ctx.term()并中断线程阻塞socket.recv().

这工作正常,但我不想终止我的整个上下文,但只是这个单个套接字.我必须为每个插槽使用一个上下文,所以我无法使用inproc.

摘要

目前我不知道除了使用超时之外如何使线程B脱离其阻塞状态,共享套接字或终止整个上下文.

这样做的正确方法是什么?

G H*_*ley 5

人们经常提到,您可以直接销毁 zmq 上下文,并且任何共享该上下文的内容都将退出,但这会造成一场噩梦,因为您的退出代码必须尽最大努力避免意外调用死套接字对象的雷区。

尝试关闭套接字也不起作用,因为它们不是线程安全的,最终会导致崩溃。

回答:最好的方法是按照 ZeroMQ 指南建议的那样通过多线程使用;使用 zmq 套接字而不是线程互斥锁/锁等。设置一个额外的侦听器套接字,您将在关闭时连接和发送一些内容,并且您的 run() 应该使用 JeroMQ 轮询器来检查您的两个套接字中的哪个接收到任何内容 - 如果附加套接字接收到一些内容,则退出。