Java中的并发和阻塞队列

Yia*_*nis 27 java queue concurrency blocking

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

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

我的第一个想法是使用a LinkedBlockingQueue,但我很快意识到它不是并发的,而且性能受到了影响.在另一方面,我现在使用ConcurrentLinkedQueue,但还是我付出的成本wait()/ notify()每本出版物上.由于消费者在找到空队列时没有阻止,因此我必须同步并wait()锁定.另一方面,制作人必须获得锁定并notify()在每一个出版物上.总体结果是sycnhronized (lock) {lock.notify()},即使不需要,我也会支付每一份出版物的费用 .

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

是这样的/合理的吗?

Ror*_*ick 12

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

  • 需要注意的是,如果您想要更高的吞吐量,请在LinkedBlcokingQueue上使用drainTo(),我们测量了其中一个应用程序的吞吐量增加了近500%,而不是从队列中取出()一个和一个元素 (7认同)

eka*_*gas 6

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

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

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

image = futureImage.get();
Run Code Online (Sandbox Code Playgroud)

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

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

boolean wasWritten = futureWrite.get();
Run Code Online (Sandbox Code Playgroud)

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


cod*_*lhu 5

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