Нужно ли синхронизировать доступ к инкапсулированным поточно-ориентированным структурам данных в Java? - PullRequest
3 голосов
/ 10 февраля 2010

Скажи, что у меня есть что-то вроде этого (и я делаю)

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

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

с некоторыми из них, которые работают в своих собственных потоках

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);
        }
    }
}

Должен ли мой poll() в QueBean быть synchronized или нет?

Ответы [ 4 ]

6 голосов
/ 10 февраля 2010

Существует проблема с многопоточностью, но не та, о которой вы думаете. Код, который вы разместили, почти наверняка является незаконным и в конечном итоге заблокируется.

Одним из основных правил Swing является то, что только одному потоку разрешено касаться «реализованных» компонентов. (Реализовано означает «на экране» или «почти» на экране).

Это:

jResultTextField.setText("got one"); 

Внутри нити почти наверняка что-то не так - вы просто не можете этого сделать. Проверьте invokeLater или invokeAndWait, чтобы получать обновления экрана в ветке AWT.

Между прочим - это забавно иметь потоки во всем, что расширяет компонент - видение, которое приводит меня к НЕМЕДЛЕННО поиску места конфликта, но это должно сделать любого давнего программиста Java с первого взгляда неловким - Я предлагаю вам разделить некоторые классы и полностью отделить часть, которая управляет вашим GUI (контроллером) от GUI (просмотр) ..

2 голосов
/ 10 февраля 2010

Внешняя синхронизация в этом случае не требуется. Прочитайте BlockingQueue контракт:

Реализации BlockingQueue потокобезопасный. Все методы очередей добиться их эффекта атомарно, используя внутренние замки или другие формы управление параллелизмом.

2 голосов
/ 10 февраля 2010

Нет. Нет нужды. Поскольку ваш метод poll ничего не делает, кроме вызова поточно-ориентированного метода, вероятность повреждения данных отсутствует.

1 голос
/ 10 февраля 2010

Вам не нужно делать это, если queue не изменяется в QueBean.

Кроме того, если вы не пытаетесь реализовать какое-то тривиальное ограничение скорости, вам не нужен wait(500) в вашем коде. Это излишне из-за блокировки очереди.

...