【问题标题】:How to interrupt BlockingQueue?如何中断 BlockingQueue?
【发布时间】:2013-03-25 04:40:36
【问题描述】:
BlockingQueue.put 可以抛出 InterruptedException。
如何通过抛出此异常导致队列中断?
ArrayBlockingQueue<Param> queue = new ArrayBlockingQueue<Param>(NUMBER_OF_MEMBERS);
...
try {
queue.put(param);
} catch (InterruptedException e) {
Log.w(TAG, "put Interrupted", e);
}
...
// how can I queue.notify?
【问题讨论】:
标签:
java
android
concurrency
blocking
interrupt
【解决方案1】:
您需要中断正在调用queue.put(...); 的线程。 put(...); 调用在某些内部条件下执行wait(),如果调用put(...) 的线程被中断,则wait(...) 调用将抛出InterruptedException,由put(...); 传递
// interrupt a thread which causes the put() to throw
thread.interrupt();
要获取线程,您可以在创建时存储它:
Thread workerThread = new Thread(myRunnable);
...
workerThread.interrupt();
或者您可以使用Thread.currentThread() 方法调用并将其存储在某个地方以供其他人使用来中断。
public class MyRunnable implements Runnable {
public Thread myThread;
public void run() {
myThread = Thread.currentThread();
...
}
public void interruptMe() {
myThread.interrupt();
}
}
最后,捕获InterruptedException 立即重新中断线程是一个很好的模式,因为当InterruptedException 被抛出时,线程上的中断状态被清除。
try {
queue.put(param);
} catch (InterruptedException e) {
// immediately re-interrupt the thread
Thread.currentThread().interrupt();
Log.w(TAG, "put Interrupted", e);
// maybe we should stop the thread here
}
【解决方案2】:
您需要使用 queue.put() 引用运行代码的线程,就像在这个测试中一样
Thread t = new Thread() {
public void run() {
BlockingQueue queue = new ArrayBlockingQueue(1);
try {
queue.put(new Object());
queue.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
};
};
t.start();
Thread.sleep(100);
t.interrupt();
【解决方案3】:
调用put 将等待一个插槽空闲,然后再添加param 并且流程可以继续。
如果您在调用put 时捕获正在运行的线程(即,在调用put 之前调用Thread t1 = Thread.currentThread()),然后在另一个线程中调用interrupt(而t1 被阻塞) .
This example 有类似的东西,它负责在给定超时后调用中断。