在写Java swing程序的时候遇到了一个EventQueue.invokLater,用来创建一个线程,展示新窗体的,之前写窗体程序都是直接实例化窗体对象,没有使用过这个方法,所以在这里总结一下EventQueue.invokLater的使用。
一、EventQueue.invokLater是什么?为什么要是用它?
①在JDK手册中查询到的内容如下:
EventQueue是一个与平台无关的类,它将来自于同位体类和受信任的应用程序类的事件列入队列。它封装了异步事件指派机制,该机制从队列中提取事件,然后通过对此EventQueue调用dispatchEvent(AWTEvent)方法来指派这些事件(事件作为缠参数被指派)。该机制的特殊行为是与实现有关的。指派实际排入到该队列的事件(注意:正在发送到EventQueue中的事件可以被合并)的唯一要求是:
按顺序指派,也就是说,不允许同时从该队列中指派多个事件。
指派顺序与他们的排队顺序相同。也就是说,如果AWTEvent A比AWTEvent B先排入到EventQueue中,那么事件B不能在事件A之前被指派。
一些浏览器将不同代码基中的applet分成独立上下文,并在这些上下文之间建立一道道墙。在这样的场景中,每个上下文将会有一个WventQueue。其他浏览器将所有applet放入到同一个上下文中,这意味着所有applet只有一个全局EventQueue。该行为是与实现有关的。更多信息参见浏览器文档。
有关事件指派机制的线程问题,参阅AWT线程问题
EventQueue.invokLater是EventQueue的一个方法,方法的作用是:使得runnable的run方法在"the system EventQueue"(获取应用程序或 applet的EventQueue 实例)的指派线程中被调用
②为何要使用EventQueue.invokLater?
awt是单线程模式的,所有awt的组件只能在(推荐方式)事件处理线程中访问,从而保证组件状态的可确定性,这样导致的后果是:只能从事件派发线程访问将要在窗口展示的swing组件。(事件派发线程:是调用paint和update等回调方法的线程,他还是事件监听器接口定义的事件处理方法,ActionListener中的actionPerformed方法就是在事件派发线程中调用。)
swing是事件驱动的,在回调函数中更新可见的GUI是很自然的事。例如,按钮按下项目列表需要更新时,则通常在与该按钮相关联的事件监听器的actionPerformed方法中来实现此操作,从事件派发线程之外的线程中更新swing组件是不正常的。但是有时需要从事件派发线程之外的线程去更新swing,比如在actionPerformed中有很费时间的操作,按钮时间触发过后需要较长的时间才能看到更新的内容,按钮长时间保持按下状态,直到actionPerformed方法返回,一般来说耗时的操作不应该在时间处理方法中执行,因为事件处理返回之前其他事件是不能被触发的,界面会处于静止状态,类似界面卡住一样,所以在独立的线程上执行比较耗时的操作很更好,这样会立即更新用户界面和释放事件派发线程去派发其他事件
二、有什么特点?用它有什么好处?
调用该方法的的好处就是可以提高性能,改善用户的使用体验,还有好处就是方法调用完成后就会销毁,因为匿名内部类是作为临时变量存在的,给其分配的内存会被释放,可以节省内存。问题也是有的,就是每次都new一个runnable,如果new的数目过多,且处理的runnable的速度不够迅速的话,那么就会出现内存泄露的问题。
三、怎么使用?Demo
EventQueue.invokeLater(new Runnable(){
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
四、什么时候使用?
上面已经提到了,从事件派发线程之外的线程去执行程序或者处理耗时较高的代码时用到。
总结分享,欢迎赐教!