Search code examples
javamultithreadingloadcpu

Huge CPU impact LinkedBlockingQueue


I have a LinkedBlockingQueue called tasks, but when I call tasks.take() and wait for a task to become available, the CPU usage is 100%. I've got multiple threads using the tasks.take() method (every thread has its own tasks variable). Does anybody know why this is happening?

Defenition of the tasks variable

private LinkedBlockingQueue<ComputerTask> tasks;
// snip
this.tasks = new LinkedBlockingQueue<ComputerTask>(100);

Code to take a task

ComputerTask task = tasks.take();

Code to offer a new task

this.tasks.offer(task);

P.S. I don't know if this is a problem with my version of Java, cause I haven't tested it on any other computers yet.

java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-413-11M3623)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-413, mixed mode)

Solution

  • I have a LinkedBlockingQueue called tasks, but when I call tasks.take() and wait for a task to become available, the CPU usage is 100%. I've got multiple threads using the tasks.take() method (every thread has its own tasks variable).

    tasks.take(); should not be spinning unless it is dequeuing a large number of items. If the queue is empty, it will block so I suspect this is not the cause of the 100% load. I would make sure you use a profiler or add debug statements around the take() to see if it is being called some large number of times.

    One thing to remember is that tasks.offer(task) returns false immediately if the queue is full. I'm wondering you should be using tasks.put(task) which will block instead and not spin. If you are using offer() to determine which task handler to run the task on, then maybe you are looping around and around when all of the task handlers' queues are full?

    If you are doing your own task management, you might consider using instead one of the built-in ExecutorService classes. You then can submit all of your tasks or use a blocking queue and the ExecutorService will handle feeding each thread in the pool its tasks:

    // start 10 threads handling the tasks
    ExecutorService threadPool = Executors.newFixedThreadPool(10);
    // now submit tasks to the pools that will be run with the 10 threads
    threadPool.submit(task);
    ...
    

    In the above example ComputerTask has to implement Runnable.