我正在编写一个Runnable类,它将消息打包在一起一段时间,或者直到达到给定的大小才能通过网络发送它们。它旨在允许其他线程在通过某些setter方法运行时更改某些内部参数(例如数据包大小)。使用内部对象锁来使run()
逻辑的某些部分与setter互斥是否正确?
类似的东西:
public class Packer implements Runnable {
private BlockingQueue<byte[]> msgQueue;
private Object lock = new Object();
private Packet packet;
private boolean running = false;
public synchronized void append(byte[] payload) throws InterruptedException {
msgQueue.put(payload);
}
public synchronized void setPacketCapacity(int size) {
synchronized (lock) {
// check to see if we need to flush the current packet first, etc.
packet.setCapacity(size);
}
}
public void run() {
running = true;
while (running) {
try {
byte[] msg = msgQueue.take();
synchronized (lock) {
packet.add(msg);
// check if we need to flush the packet, etc.
}
} catch (InterruptedException ex) {
logger.warn("interrupted");
running = false;
} catch (Exception e) {
logger.error(e);
}
}
logger.warn("stop");
}
}
相关地,另一个线程告诉这个runnable停止(和刷新)的正确方法是什么?
由于run()
方法可能正在等待内部队列msgQueue
,因此仅设置running=false
可能不够,我可能不得不中断该线程。或者,我可以向内部队列发送一个特殊的“End Of Stream”消息,但如果队列已满,我可能需要等待一段时间才能被接受。
答案 0 :(得分:0)
setter
和run()
内部的逻辑,因此是正确的。我建议您从设置器方法签名中删除synchronized
,因为您已经用锁定对象锁定了其中的所有代码您可以删除boolean running
并像这样写run()
:
public void run() {
while (true) {
try {
byte[] msg = msgQueue.take();
synchronized (lock) {
packet.add(msg);
// check if we need to flush the packet, etc.
}
} catch (InterruptedException ex) {
logger.warn("interrupted");
Thread.currentThread.interrupt();
return;
} catch (Exception e) {
logger.error(e);
}
}
logger.warn("stop");
}
调用thread.interrupt()
将强制run()
方法中的代码转到InterruptedException catch块,在该块中设置中断标志并从run()