我想知道如何正确关闭 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();
}
}
这很好用。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);
}
线程 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 脱离阻塞状态。
这样做的正确方法是什么?