我正在开发我的第一个多线程项目,因此有一些我不确定的事情。有关我的设置的详细信息位于previous question,简而言之:我有一个由Executors.newFixedThreadPool(N)
实现的线程池。给一个线程一个操作,该操作对本地和远程资源执行一系列查询,并迭代填充ArrayBlockingQueue
,而其余线程在队列上调用take()
方法并处理队列中的对象。
即使小型和监督测试似乎运行正常,我也不确定我如何处理特殊情况,例如开头(队列还没有项目),结束(队列已清空),以及任何最终{{ 1}}。我在SO上做了一些阅读,然后由Goetz和Kabutz引导我阅读了两篇非常好的文章。共识似乎是不应忽视这些例外。但是我不确定所提供的示例是如何与我的情况相关的,我没有在我的代码中的任何地方调用InterruptedExceptions
......说到这一点,我不确定我是否应该这样做......
总结一下,鉴于下面的代码,我如何最好地处理特殊情况,例如终止条件和InterrruptedExceptions?希望问题有意义,否则我会尽力进一步描述。
提前致谢,
编辑:我一直在努力实施一段时间,我遇到了一个新的打嗝,所以我想我会更新情况。我遇到了thread.interrupt()
的不幸,这很可能是由于线程池的不完全关闭/终止造成的。一旦我发现我可以使用ConcurrentModificationException
我尝试了,然后由于未同步的isTerminated()
我得到IllegalMonitorStateException
。代码的当前状态如下:
我已经听过@ Jonathan的回答中的一些建议,但是我不认为他的建议与我需要/想要的一样。背景故事与我上面提到的相同,相关的代码如下:
持有/管理池的类,以及提交runnables:
wait()
元素通过位于单独类中的以下代码添加到队列中:
public void serve() {
try {
this.started = true;
pool.execute(new QueryingAction(pcqs));
for(;;){
PathwayImpl p = bq.take();
if (p.getId().equals("0")){
System.out.println("--DEBUG: Termination criteria found, shutdown initiated..");
pool.shutdown();
// give 3 minutes per item in queue to finish up
pool.awaitTermination(3 * bq.size(), TimeUnit.MINUTES);
break;
}
int sortMethod = AnalysisParameters.getInstance().getSort_method();
pool.submit(new AnalysisAction(p));
}
} catch (Exception ex) {
ex.printStackTrace();
System.err.println("Unexpected error in core analysis, terminating execution!");
System.exit(0);
}finally{ pool.shutdown(); }
}
public boolean isDone(){
if(this.started)
return pool.isTerminated();
else
return false;
}
...... this.queue.offer(path, offer_wait, TimeUnit.MINUTES);
而不是offer()
背后的动机正如乔纳森所提到的那样。不可预见的块很烦人,很难弄清楚,因为我的分析花了很长时间。因此,如果由于坏块而失败,或者它只是处理数字,我需要知道相对较快...
最后;这是我的测试类中的代码,我在其中检查“并发服务”(此处命名为cs)与要分析的其余对象之间的交互:
take()
我意识到这是一个非常长的问题,但我试图详细而具体。希望它不会太拖累,我道歉,以防它... ...
答案 0 :(得分:1)
不使用take
哪个块,而是使用更像这样的东西:
PathwayImpl p = null;
synchronized (bq) {
try {
while (bq.isEmpty() && !stopSignal) {
bq.wait(3000); // Wait up to 3 seconds and check again
}
if (!stopSignal) {
p = bq.poll();
}
}
catch (InterruptedException ie) {
// Broke us out of waiting, loop around to test the stopSignal again
}
}
这假设该块包含在某种while (!stopSignal) {...}
。
然后,在添加到队列的代码中,执行以下操作:
synchronized (bq) {
bq.add(item);
bq.notify();
}
至于InterruptedException
,它们很适合用信号通知线程立即测试停止信号,而不是等到下一次超时测试。我建议再次测试你的停止信号,并可能记录异常。
我在发出恐慌信号时使用它们,而不是正常关机,但很少需要这种情况。