《FilthyRichClients》读书笔记(一)-SwingのEDT - 编程入门网
queue.add(e);
LOCK.notifyAll();
}
}
}
在JDK 5中新出现了许多具有并发性的数据结构在java.util.concurrent包中,它们适合于特殊的场合,本帖不作解释。 事件队列:在计算机数据结构中,队列是一个特殊的数据结构。其一、它是线性的;其二、元素是先进先出的,也就是说进入队列的元素必须从末端进入,先入队的元素先得到执行,后入队的元素等待前面的元素执行完毕出队后才能执行,队列的处理方式是执行完一个再执行下一个。队列与线程安全是两个不同的概念,如果要将队列加上线程安全的特性,只需要仿照上述生产者/消费者加上线程的等待/通知即可。 而Swing的事件队列就类似(基本原理相似,但是Swing内部实现会做些优化)于上述的事件队列,说它是单线程图形工具包指的是仅有单一消费者,也就是常说的事件分发线程(EDT),一般来讲,除非你的应用程序停止,否则EDT会永不间断地徘徊在处理请求与等待请求之间。下图是Swing事件队列的实现机制: 《FilthyRichClients》读书笔记(一)-SwingのEDT(3)时间:2011-06-29 BlogJava javagui很显然,如果在加工某一个货物上花费很长的时间,那么后续的货物只好等待。对于单一线程的事件队列来说有两个非常突出的特性:一、将同步操作转为异步操作。二、将并行处理转换为串行顺序处理。 如果你能理解上述图,那么你就应该意识到:EDT要处理所有GUI操作,它是职责分明且非常忙碌的。也就是说你要记住两条原则:一、职责分明,任何GUI请求都应该在EDT中调用。二、需要处理的GUI请求非常多,包括窗口移动、组件自动重绘、刷新,它很忙,所以任何与GUI无关的处理不要由EDT来负责,尤其是I/O这种耗时的操作。 书中还讲到Swing不是一个“安全线程”的API,为什么要这样设计,再回看上图就会明白:Swing的线程安全不是靠自身组件的API来保障,虽然repaint方法是这样,但是大多数Swing API是非线程安全的,也就是说不能在任意地方调用,它应该只在EDT中调用。Swing的线程安全靠事件队列和EDT来保障。 invokeLater和invokeAndWait:前文提到,Swing自身不是线程安全,对非EDT的并发调用需通过invokeLater(runnable)和invokeAndWait(runnable)使请求插入到队列中等待EDT去执行。invokeLater(runnable)方法是异步的,它会立即返回,具体何时执行请求并不确定,所以命名invokeLater是稍后调用。invokeAndWait(runnable)方法是同步的,它被调用结束会立即block当前线程(调用invokeAndWait的那个线程)直到EDT处理完那个请求。invokeAndWait一般的应用是取得Swing组件的数据,例如取得JSlider组件的当前值:
而外部非EDT线程可以这样调用:
《FilthyRichClients》读书笔记(一)-SwingのEDT(4)时间:2011-06-29 BlogJava javagui当线程运行到EventQueue.invokeAndWait(task)时会立即被block至少1秒,待invokeAndWait返回时已经可以安全地取到值了。invokeAndWait被这样命名也反映了使用的意图:调用并等待结果。invokeAndWait有非常重要的一条准则是它不能在EDT中被调用,否则程序会抛出Error,请求也不会去执 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |