在书上看到,swing是线程不安全的,对swing组件的操作最好用SwingUtilities.invokeLater()或SwingUtilities.invokeAndWait()
public class TestSwing {
  
  private List<JLabel> jls;
  private GridBagConstraints gbc;
  
  public TestSwing() {
    this.setLayout(new GridBagLayout());
  }  public void initGUI() {
    /*
     *这里是gbc的设定等
     */
    for (JLabel jl: jls) {
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          TestSwing.this.add(jl);//eclipse一直提示这里的jl是非final的,编译错误
        }
      });
    }
  }  public static void main(String arg[]) {
    TestSwing ts = new TestSwing();
    ts.setVisible(true);
  }
}
如果initGUI()改为如下:........public void initGUI() {
  SwingUtilities.invokeLater(new Runnable() {
    /*
     *这里是gbc的设定等
     */
    for (JLabel jl: jls) {
      TestSwing.this.add(jls);
    }
  });
}........
请问:
1、在run()里只放入TestSwing.this.add(jl)的话,eclipse一直报错(jl不是final);而如果改把所有gbc、foreach等都放入run()里面,我觉得是否有点过度使用SwingUtilities的线程分派了?改怎样写这个线程安全的initGUI()啊?2、在initGUI()里使用SwingUtilities.invokeLater()时,是否仍需要使用ReentrantLock来锁定initGUI()里的所有资源?

谢谢

解决方案 »

  1.   

     SwingUtilities.invokeLater(new Runnable() {
            public void run() {
             new TestSwing();
                     }
      

  2.   

    学习了,我平时都这么用的。。public static void main(String[] args) {
    try {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {
    e.printStackTrace();
    }
    new Gui();
    }
      

  3.   


    嗯谢了。如果TestSwing是个静态不变的界面,也许这样就行。而如果TestSwing里面有很多复杂的GUI组件并且有listener改变GUI的状态,那么那些改变GUI状态的代码也应该写入invokeLater(),这样的话看起来线程安全问题不是上面这样写能够解决的吧?