我遇到以下示例代码的问题,该代码显示了EventQueue的不一致行为:
public static void main( String[] args ) throws InvocationTargetException, InterruptedException {
final long[] id1 = new long[ 1 ];
final long[] id2 = new long[ 1 ];
EventQueue.invokeAndWait( new Runnable() {
@Override public void run() {
id1[ 0 ] = Thread.currentThread().getId();
}
} );
Thread.sleep( 5000 );
EventQueue.invokeAndWait( new Runnable() {
@Override public void run() {
id2[ 0 ] = Thread.currentThread().getId();
}
} );
System.out.println( "id1 = " + id1[0] );
System.out.println( "id2 = " + id2[0] );
if(id1[0]!=id2[0]){
System.out.println("These ID's don't match, even though they were retrieved from the same thread.");
}
}
基本上,它获取事件队列线程的ID,等待5秒,然后再次获取ID。
由于某种原因,ID不匹配。显然,EventQueue被破坏并重新创建。这是正常的行为吗?这是在某处记录的吗?这是一个错误吗?即使它是一个不同的实例,它不应该具有相同的ID吗?
如果我不执行Thread.sleep
,则ID将匹配。
我的另一个问题是:我怎样才能解决这个问题?我正在使用只能在创建线程上访问的对象。如果这恰好是事件队列(它不一定是必须的),我必须能够检查它是否仍然是事件队列。
答案 0 :(得分:2)
当不再需要AWT事件调度线程 时,将被关闭(this page描述了JDK 7中实际实现的规范和行为。)
这似乎发生在这里:您使用系统EventQueue
来处理一个事件。然后再也不需要它了(没有AWT / Swing组件,......)。一段时间后它就会关闭。
然后,当您再次使用EventQueue
时,另一个线程将开始接管该角色。
所以这里发生的是你的Runnable.run()
方法做在两个不同的线程上执行。 两个线程都是“AWT事件调度线程”,只是在JVM生命周期的不同时间。
使用EventQueue.isDispatchThread()
可能是一种可能的解决方案。