从问题开始说.
我们产品的 操作台(workbench) 是一个java swing程序. 有一个event handler的代码如下:
public void actionPerformed(ActionEvent e) { // 做耗时的工作, 如插入数据库 }
现在的一个问题在于, 如果用户连续点了两次button, 则event handler被执行两次, 则用户会得到 主键重复错误.
简单的想法是 在event handler的开头结尾把 对应的ok button给disable/enable.
public void actionPerformed(ActionEvent e) { try { // disable OK 按钮... // 做耗时的工作 } finally { // enable OK 按钮... } }
但上面这段代码是错误的.
event dispatch thread的工作流程:
enter handling code of event1 -> disable button -> enable button -> enter handling code of event2
正确的实现:
public void actionPerformed(ActionEvent e) { try { // disable OK 按钮... // 做耗时的工作 } finally { SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { // enable OK 按钮... }}); } }
event dispatch thread的工作流程:
enter handling code of event1 -> disable button -> ignore event2 -> enable button
If invokeLater is called from the event dispatching thread -- for example, from a JButton's ActionListener -- the doRun.run() will still be deferred until all pending events have been processed.
references:
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/
https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)