Мое понимание: В отличие от большинства компонентов/операций в вызове Swing для JComponent.repaint() является потокобезопасным, т.е. Хотя запрос перерисовки выполняется из другого потока (то есть не из EDT), фактическая картина происходит только в EDT. Ниже приведен фрагмент кода.
public class PaintingDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JPanel p = new MyPanel();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.add(p, BorderLayout.CENTER);
frame.setSize(200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
new Thread("MyThread") {
public void run() {
while (true) {
// Below statements are important to show the difference
p.repaint();
p.paintImmediately(p.getBounds());
try {
Thread.sleep(1000);
} catch(Exception e) {}
}
}
}.start();
}
}
class MyPanel extends JPanel {
@Override
public void paint(Graphics g) {
System.out.println("paint() called in "+ Thread.currentThread().getName());
super.paint(g);
}
}
Из вывода известно, что рисование выполняется в EDT при вызове repaint(), независимо от того, из какого потока он вызван, поэтому проблем нет. Но в случае paintImmediately() - живопись происходит в том же потоке, из которого он вызывается.
Рассмотрим случай, когда EDT изменяет состояние компонента и другой поток (из которого вызывается paintImmediately()) рисует тот же компонент.
Мой вопрос: В случае paintImmediately(), как выполняется синхронизация между потоком Dispatcher потока (EDT) и другими потоками?