Java中的并发和阻塞队列

我有一个线程将事件推送到第二个线程的传入队列的经典问题。 只有这一次,我对表现很感兴趣。 我想要实现的是:

  • 我希望并发访问队列,生产者推送,接收器弹出。
  • 当队列为空时,我希望使用者阻塞队列,等待生产者。

我的第一个想法是使用LinkedBlockingQueue ,但我很快意识到它不是并发的,性能受到了影响。 另一方面,我现在使用ConcurrentLinkedQueue ,但我仍然在每个发布上支付wait() / notify()的成本。 由于消费者在找到空队列时没有阻塞,因此我必须在锁上进行同步和wait() 。 另一方面,生产者必须获得该锁定并在每个出版物上notify() 。 总体结果是我在每个出版物中支付sycnhronized (lock) {lock.notify()}的成本,即使不需要也是如此。

我想这里需要的是一个阻塞和并发的队列。 我想象一个push()操作在ConcurrentLinkedQueue工作,当push元素是列表中的第一个元素时,对象提供额外的notify() 。 我认为这样的检查已经存在于ConcurrentLinkedQueue ,因为推送需要连接下一个元素。 因此,这比每次在外部锁上同步要快得多。

是这样的/合理的吗?

我认为你可以坚持使用java.util.concurrent.LinkedBlockingQueue而不管你的疑惑。 它是并发的。 虽然,我不知道它的表现。 可能, BlockingQueue其他实现将更适合您。 其中没有太多,所以进行性能测试和测量。

类似于这个答案https://stackoverflow.com/a/1212515/1102730但有点不同..我最终使用了ExecutorService 。 您可以使用Executors.newSingleThreadExecutor()实例化一个。 我需要一个并发队列来读取/写入BufferedImages文件,以及读取和写入的primefaces性。 我只需要一个线程,因为文件IO比源,网络IO快几个数量级。 此外,我更关注动作的primefaces性和正确性而不是性能,但是这种方法也可以通过池中的多个线程来完成,以加快速度。

获取图像(Try-Catch-Finally省略):

 Future futureImage = executorService.submit(new Callable() { @Override public BufferedImage call() throws Exception { ImageInputStream is = new FileImageInputStream(file); return ImageIO.read(is); } }) image = futureImage.get(); 

保存图像(Try-Catch-Finally省略):

 Future futureWrite = executorService.submit(new Callable() { @Override public Boolean call() { FileOutputStream os = new FileOutputStream(file); return ImageIO.write(image, getFileFormat(), os); } }); boolean wasWritten = futureWrite.get(); 

重要的是要注意,您应该在finally块中刷新和关闭流。 与其他解决方案相比,我不知道它的表现如何,但它非常通用。

我建议你看一下ThreadPoolExecutor newSingleThreadExecutor。 它将处理为您订购的任务,如果您将Callables提交给执行者,您将能够获得您正在寻找的阻止行为。

您可以尝试jsr166中的LinkedTransferQueue: http ://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166y/

它满足您的要求,并且提供/轮询操作的开销更少。 正如我从代码中看到的,当队列不为空时,它使用primefaces操作来轮询元素。 当队列为空时,它会旋转一段时间并停止线程,如果不成功。 我认为这对你的情况有帮助。

每当我需要将数据从一个线程传递到另一个线程时,我就使用ArrayBlockingQueue。 使用put和take方法(如果满/空将阻止)。

以下是实现BlockingQueue的类列表 。

我建议查看SynchronousQueue

就像@Rorick在评论中提到的那样,我相信所有这些实现都是并发的。 我认为您对LinkedBlockingQueue的担忧可能LinkedBlockingQueue