首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正确关闭JeroMQ

正确关闭JeroMQ
EN

Stack Overflow用户
提问于 2014-03-27 11:46:25
回答 2查看 2.4K关注 0票数 8

我想知道如何正确地关闭JeroMQ,到目前为止,我知道三种方法都有各自的优缺点,我不知道哪一种是最好的。

情况:

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

我现在的方法是:

螺纹A

代码语言:javascript
复制
static ZContext CONTEXT = new ZContext();
Thread thread;

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

public void stop() {
    thread.stopping = true;
    thread.join();
}

螺纹B

代码语言:javascript
复制
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();
    }
}

这真是太好了。10 is关闭对我来说不是问题,但当没有收到消息时,我会不必要地增加CPU负载。现在我更喜欢这个。

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

螺纹A

代码语言:javascript
复制
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);
}

螺纹B

代码语言:javascript
复制
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();
        }
    }
}

它也很有魅力,但是即使recv已经阻止了异常,有时也不会被抛出。如果我在启动线程A之后等待了1毫秒,异常总是会被抛出。我不知道这是一个bug,还是我滥用的结果,因为我共享这个套接字。

"revite“之前问过这个问题(https://github.com/zeromq/jeromq/issues/116),并得到了第三个解决方案:https://github.com/zeromq/jeromq/blob/master/src/test/java/guide/interrupt.java

摘要:他们调用ctx.term()并在socket.recv()中中断线程阻塞。

这很好,但是我不想终止我的整个上下文,而只是终止这个单一的套接字。我必须在每个套接字上使用一个上下文,所以我不能使用inproc。

摘要

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

正确的做法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-01 23:25:32

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

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

答:最好的方法是按照ZeroMQ指南的建议,通过多个线程进行任何使用;使用zmq套接字,而不是使用线程互斥/锁/等等。设置一个额外的侦听器套接字,在关机时连接和发送一些东西,您的run()应该使用JeroMQ Poller来检查您的两个套接字中哪个接收到任何东西--如果附加套接字接收到了什么,那么就退出。

票数 5
EN

Stack Overflow用户

发布于 2014-04-30 01:41:51

查看jeromq源这里,即使在执行“阻塞”recv时,您仍然在消耗整个时间的CPU (线程从不休眠)。如果您担心这一点,那么让第二个线程在轮询之间休眠,然后让父线程中断。类似于(只是相关的部分):

螺纹A

代码语言:javascript
复制
public void stop() {
    thread.interrupt();
    thread.join();
}

螺纹B

代码语言:javascript
复制
while (!Thread.interrupted()) {
  socket.recv(); // do whatever
  try {
    Thread.sleep(10); //milliseconds
  } catch (InterruptedException e) {
    break;
  }
}

另外,关于第二种解决方案,通常您不应该在线程之间共享套接字-- 零Q导轨对此非常清楚--“不要在线程之间共享on套接字。on套接字不是线程安全。”请记住,ZMQ的一个主要用途是通过连接的套接字通信的IPC线程,而不是共享一个套接字的同一端。不需要共享布尔停止变量之类的东西。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22686651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档