views:

1486

answers:

2

I have two threads. Thread A is pulling some elements from queue and thread B is adding some elements to the queue.

I want thread A to go to sleep when the queue is empty.

When thread B adds some element to the queue it should make sure that thread A is working. How can this be done in Java?

+12  A: 

Use a BlockingQueue, which is:

A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.

Seriously, don't try to reinvent the wheel here.




(If you must use wait/notify, read this tutorial. But spare yourself the pain, please!)

Michael Myers
Thanks.. I learnt a new thing :)
Chathuranga Chandrasekara
+1  A: 

Here are some details:

import java.concurrent.Executors;
import java.concurrent.ExecutorService;
...
ExecutorService executor = Executors.newFixedThreadPool(someNumberOfThreads);
...
executor.execute(someObjectThatImplementsRunnable);
...
executor.shutdownNow();

That's all there is to it with Java's newer threading capabilities. Executor is a thread pool with someNumberOfThreads in it. It is fed by a blocking queue. All the threads sleep unless there is work to do. When you push a Runnable object into the queue using the execute() method, the Runnable object sits in the queue until there is a thread available to process it. Then, it's run() method is called. Finally, the shutdownNow() method signals all threads in the pool to shutdown.

It's much simpler now than it used to be.

(There are lots of variations on this, such as pools with minimum and maximum numbers of threads, or queues which have maximum sizes before threads calling execute() will block.)

Clint Miller
Note that this isn't really what you want to use for long-lived threads. It's more for when you have some short tasks that you want to deal with. For example, if you have a thread pulling events from a queue, and then doing something with those events, the thread pulling the events from the queue probably shouldn't be pooled, but it might use a thread pool to do whatever it's going to do with each event concurrently. You never want pooled threads to be waiting on something, especially in a fixed-size pool.
Adam Jaskiewicz
Interesting. I'm curious what the reason is for this. We're doing exactly what you're warning against in a couple places in our application, and I'm curious about where that might get us into trouble.
Clint Miller
Thread pools serve two primary purposes: first, you reduce thread-creation overhead by re-using threads, and second, you can control how many Runnables you are giving CPU to at a time. Both of these purposes are great for CPU-bound tasks, like number crunching, and other short-term stuff that you want to run concurrently. Something like a consumer thread is going to sit there waiting until there is something to consume, then it will do its thing, and go back to waiting. Most of its time is spent waiting, which means you have one less usable thread in your pool.
Adam Jaskiewicz
Now, this isn't an issue if you're using a non-fixed pool, but then you lose the second purpose of a thread pool: control over the level of concurrency of your CPU-bound tasks. You *could* create two thread pools; one of unlimited size for your long-term, non-CPU-bound stuff that spends most of its time waiting on some other part of the system, and a fixed-size pool for your short-term tasks, but the former type of thread doesn't really benefit from being in a thread pool, and arguably the paradigm of "submitting tasks" doesn't fit stuff that has a similar lifetime to the application itself.
Adam Jaskiewicz