我是否必须在Java中同步对封装的线程安全数据结构的访问?

bla*_*ank 3 java concurrency synchronized

说我有这样的事情(我也这样做)

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

    public Object poll(){
        return queue.poll();
    }
}
Run Code Online (Sandbox Code Playgroud)

其中一些运行在自己的线程上

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该poll()QueBeansynchronized或不是?

Bil*_*l K 6

有一个线程问题,但不是你认为的问题 - 你发布的代码几乎肯定是非法的,最终会锁定.

Swing的核心规则之一是只允许一个线程触及"已实现"的组件.(已实现意味着在屏幕上或"几乎"在屏幕上).

这个:

jResultTextField.setText("got one"); 
Run Code Online (Sandbox Code Playgroud)

在一个线程内部肯定是错的 - 你就是做不到.检查invokeLater或invokeAndWait以获取您的AWT线程的屏幕更新.

顺便说一下 - 在扩展组件的任何东西中都有线程感觉很有趣 - 看到这导致我立即搜索冲突的位置,但是它应该让任何长期的Java程序员一眼就感到不安 - 我建议你将您的类拆分一些,并将驱动GUI(Controller)的部分与GUI(视图)完全分开.

  • 非法我的意思是它会工作很长一段时间,但偶尔你会看到GUI上的故障或GUI会挂起.最终你会开始看到更严重的问题 - 过了一段时间,它似乎开始似乎对你的GUI布局的每一次修改都以不可预测的方式打破了某些东西.每当您修改屏幕上的任何内容以修复它时,请使用invokeLater或invokeAndWait. (3认同)
  • `java.awt.EventQueue.invokeLater`就是你想要的. (2认同)
  • @Bedwyr:GUI更新(或导致它的任何事情,例如更新模型)_must_发生在EDT上,没有其他线程,或者你冒着未定义的行为风险.因此,"更安全"是一种严重的轻描淡写.:-) (2认同)