gpt4 book ai didi

sockets - JeroMQ 正确关闭

转载 作者:行者123 更新时间:2023-12-04 11:38:19 27 4
gpt4 key购买 nike

我想知道如何正确关闭 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();
    }

    线程 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();
    }
    }

    这很好用。关闭 10 毫秒对我来说没有问题,但是当没有收到消息时,我会不必要地增加 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);
    }

    线程 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();
    }
    }
    }

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

    “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 脱离阻塞状态。

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

    最佳答案

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

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

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

    关于sockets - JeroMQ 正确关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22686651/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com