views:

1718

answers:

3

Hi all,

My first question is what exactly happens when there is nothing on the queue and a take() is called. The API says the method will wait but does that mean the CPU spins checking for empty/not empty until an item is on the queue or does it mean that the thread yields and will be awoken by an interrupt? If it is the case of the former, I would probably want to see if the queue is empty and if it is call thread.yield() to give up processor time. My question is really do I need to call yield or does some inner mechanism handle that for me?

Secondly, what is the interrupted exception meant for? If I understand correctly it means that if thread A is executing this method and is waiting for input and another thread B calls threadA.interrupt() then thread A will catch the interrupted exception and presumably pause execution, if it is nice. Is that the correct way of thinking about it?

Please let me know.

Thanks, jbu

+4  A: 

The wait() call does not spin, it typically uses OS services to wait for an event/condition - which puts the thread to sleep until the condition/event is signaled again. No processor time is used while waiting.

You typically get the interrupted exception if the thread is blocking in a wait() call, and another thread calls interrupt() on that blocking thread, just like you said.

nos
how do i KNOW that waiting for the event/condition will put the thread to sleep? in other words, the api doesn't say the thread will be put to sleep and be signaled to wake up so how do I know what the method will actually do?
jbu
You look at the source code, which is available from Sun. If you're using another Java implementation, I don't know.
nos
I have not found the source which I have googled for
jbu
Source code referenced in my answer below
Brian Agnew
You don't know as the API does not specifically tell you it does. However you can write a test program that hangs on a condition and profile the program and/or the OS to see if it spends CPU while it is waiting. I know of no jvm/os combination where it does active spins
nos
A: 

It is considered a bad practice to call yield() as it cannot ensure niceness - you may call it and the scheduler instantly returns to your thread as it were a no-op. Use timed waits (e.g. wait(1000)) instead.

Interruptions are a safe way to signal a thread that you want something from it - stop processing, wake up and respond to something, etc.

In general, these things depend on your concrete scenarios. Java has some nice features about concurrency which can be more applicable to a situation.

kd304
It is bad practice to use busy loops. If you nevertheless use a busy loop then it is better with Thread.yield() than without.
starblue
This is the problem with yield turning into a busy loop due its nature. Imagine a 2 threaded application running on a dual core CPU. Yielding in either thread would be useless and pointless. Using await/signal instead is always a better option
kd304
+2  A: 

Note that BlockingQueue is an interface. So what follows is implementation dependent. If you look at the source code for (say) LinkedBlockingQueue, the source for take() calls lockInterruptibly() on a RentrantLock. From the doc for this:

If the lock is not available then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens:

* The lock is acquired by the current thread; or
* Some other thread interrupts the current thread, and interruption of

lock acquisition is supported.

I suspect there's be some wait()/notify() or similar going on. Will it spin the CPU ? No (check via top or similar)

Re. your question on interrupts, the Java Specialist newsletter had a very interesting article on interrupt() and catching/handling the InterruptedException.

Read the article, but essentially if you catch the exception, you reinterrupt:

  try {
        Thread.sleep(1000);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt(); // very important
        break;
      }
Brian Agnew
very helpful, thanks
jbu