views:

86

answers:

4

Say I have something like this (and I do)

class QueBean extends JPanel {
    private Queue queue = new LinkedBlockingQueue();

    public Object poll(){
        return queue.poll();
    }
}

with some of these that run on their own threads

class ConsumerBean extends JPanel implements Runnable{
    private QueBean queBean;

    public synchronized run(){
        while (true) {
           Object result =  queBean.poll();
           if (result != null) {
              jResultTextField.setText("got one");  
           }
           wait(500);
        }
    }
}

Should my poll() in the QueBean be synchronized or not?

+2  A: 

No. There is no need. Since your poll method does nothing except call a thread-safe method, there is no possibility of data corruption.

Matthew Flaschen
+1  A: 

You don't need to do this, so long as queue does not change in QueBean.

Also, unless you're trying to implement some kind of trivial rate-limitng, you don't need the wait(500) in your code. It's superfluous due to the queue being blocking.

0xfe
i am doing some trivial rate-limiting ;)
Bedwyr Humphreys
+6  A: 

There is a threading problem, but not the one you think--The code you posted is almost certainly illegal and will eventually lock up.

One of the core rules of Swing is that only one thread is allowed to touch "realized" components. (Realized means on-screen or "almost" on-screen).

This:

jResultTextField.setText("got one"); 

Inside a thread is pretty sure to be wrong--you just can't do it. Check out invokeLater or invokeAndWait to get your screen updates onto your AWT thread.

By the way--it feels funny having threads in anything that extends a component--seeing that lead me to IMMEDIATELY search for where the conflict was, but it should make any long-time Java programmer uneasy at a glance--I suggest you split up your classes some and completely separate the part that drives your GUI (Controller) from the GUI (View)..

Bill K
What do you mean by illegal? It certainly compiles and runs. (the textField method call is in another private method)
Bedwyr Humphreys
`java.awt.EventQueue.invokeLater` is what you want.
Tom Hawtin - tackline
So if i fire the GUI update on the EventQueue it will be safer?
Bedwyr Humphreys
@Bedwyr: GUI updates (or anything that causes it, such as updating models) _must_ happen on the EDT, and no other thread, or you risk undefined behaviour. So, "safer" is a serious understatement. :-)
Chris Jester-Young
By Illegal I mean that it will work for a long while, but occasionally you will see glitches on the GUI or the GUI will hang. Eventually you will start to see more serious problems--after a while it starts to seem like every modification to your GUI layout breaks something in unpredictable ways. Use invokeLater or invokeAndWait whenever you modify anything on the screen to fix it.
Bill K
@Bill: +1 for articulating what the UB bogeyman looks like. :-)
Chris Jester-Young
Thanks guys, I was seeing an error where after a while (5k events) the consumers reported consuming 1 more event than was generated. Putting the gui update on the EventQueue *seems* to have fixed this, but I'm going to refactor to have the gui listen for events in order to update itself. Now, what do I accept as an answer ...? should I change the question title?
Bedwyr Humphreys
Mine didn't actually answer the question you asked--I'd select one of the others that said you didn't have a problem.
Bill K
+1  A: 

External synchronization is not necessary in this case. Read the BlockingQueue contract:

BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control.

erickson