Search code examples
javaconcurrencyblockingqueuefork-join

BlockingQueue's put() and high concurrency


I'm using the Fork/Join Framework to do a lot of calculations in parallel. I've implemented the Producer-Consumer Pattern with a simple logger to create console outputs while the programm is calculating. The producer and consumer share a BlockingQueue and I use the put() method so I don't miss an update.

I've recognized that the performance is horrible under some circumstances and VisualVM showed me that the put() method is the cause.

When there's a problem putting new messages into the BlockingQueue my RecursiveTasks have to wait but the ForkJoinPool continues to fork new tasks so 2000-5000 tasks are trying to access the put() method which results in very high concurrency.

Is there a proper way to handle such situations?

I thought something like

if(!blockingQueue.offer(message) {
    blockingQueue.put(message);
}

could be more performant when using a theoretically unlimited BlockingQueue.

So my Question is: Is there a proper and performant way to put Objects into a BlockingQueue without loosing an update?

Thank you in advance!


Solution

  • If your pool is spawning 2000-5000 tasks then that is your problem. Once that many tasks get going you will start seeing thread contention in BlocingQueue.put which will push up the statistics for put.

    The whole point of using a BlockingQueue is so that if the consumer is slower (even temporarily) than the producer then the producer will block until the consumer has caught up. This should then cause the up-stream processes to wait too. If this is causing your upstream process (presumably the FJP) to tank the system rather than just block then that will be a problem.

    I would suggest you use a fixed-capacity FJP.