I am wondering how to close JeroMQ correctly, so far I know three methods in which everyone has their pros and cons, and I do not know which one is the best.
Situation:
- Theme A: owns context, provides start / stop methods
- Topic B: Actual Listener Stream
My current method:
Theme 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(); }
Thread 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(); } }
It works just fine. 10 ms to shutdown is not a problem for me, but I will unnecessarily increase the load on the CPU when there are no messages. At the moment, I prefer this one.
The second method splits the socket between two threads:
Theme A
static ZContext CONTEXT = new ZContext(); ZMQ.Socket socket; Thread thread; public void start() { socket = CONTEXT.createSocket(ROUTER); ...
Thread 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(); } } }
It works like a charm, but even if recv already blocks the exception, it sometimes fails. If I wait one millisecond after the start of thread A, there will always be an exception. I don't know if this is a mistake or just the result of my misuse, as I am sharing a socket.
"revite" asked this question earlier ( https://github.com/zeromq/jeromq/issues/116 ) and received an answer, which is the third solution: https://github.com/zeromq/jeromq/blob/master/src /test/java/guide/interrupt.java
Summary: They call ctx.term() and break the thread lock in socket.recv() .
This works fine, but I don't want to interrupt my entire context, but only this single socket. I would have to use one context for each socket, so I could not use inproc.
Summary
At the moment, I donβt know how to get thread B from its blocking state, besides using timeouts, split the socket or complete the whole context.
What is the right way to do this?