如下阻塞队列+线程的代码,很常见,当服务停止时,如何停止被BlockingQueue阻塞的线程?
public class BlackingQueueTest {
public static void main(String[] args) {
BlockingQueue blockingQueue = new ArrayBlockingQueue(10);
blockingQueue.add(5);
blockingQueue.add(-1);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Integer el = blockingQueue.take();
System.out.println(el);
} catch (InterruptedException e) {
}
}
}
});
thread.start();
}
}
两种解决方案
方案一:使用poll代替take
,这将允许处理线程在等待一段时间而没有新输入时超时并终止。
public class BlackingQueueTest {
public static void main(String[] args) {
BlockingQueue blockingQueue = new ArrayBlockingQueue(10);
blockingQueue.add(5);
blockingQueue.add(-1);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Integer el = blockingQueue.poll(5, TimeUnit.SECONDS);
System.out.println(el);
if (el == null) {
break;
}
} catch (InterruptedException e) {
}
}
}
});
thread.start();
}
}
方案二:判断BlockingQueue是否未空,中断处理
public class BlackingQueueTest {
public static void main(String[] args) {
BlockingQueue blockingQueue = new ArrayBlockingQueue(10);
blockingQueue.add(5);
blockingQueue.add(-1);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Integer el = blockingQueue.take();
System.out.println(el);
if (el == null) {
break;
}
} catch (InterruptedException e) {
}
}
}
});
thread.start();
}
}
优化方案:解决两个问题
BlockingQueue
以便它知道它不必等待更多元素class MyObjHandler implements Runnable
{
private final BlockingQueue queue;
public volatile boolean Finished; //VOLATILE GUARANTEES UPDATED VALUE VISIBLE TO ALL
public MyObjHandler(BlockingQueue queue)
{
this.queue = queue;
Finished = false;
}
@Override
public void run()
{
while (true)
{
try
{
MyObj obj = queue.poll(100, TimeUnit.MILLISECONDS);
if(obj!= null)//Checking if job is to be processed then processing it first and then checking for return
{
// process obj here
// ...
}
if(Finished && queue.isEmpty())
return;
}
catch (InterruptedException e)
{
return;
}
}
}
}
public void testHandler()
{
BlockingQueue queue = new ArrayBlockingQueue(100);
MyObjHandler handler = new MyObjHandler(queue);
new Thread(handler).start();
// get objects for handler to process
for (Iterator i = getMyObjIterator(); i.hasNext(); )
{
queue.put(i.next());
}
// what code should go here to tell the handler to stop waiting for more objects?
handler.Finished = true; //THIS TELLS HIM
//If you need you can wait for the termination otherwise remove join
myThread.join();
}