cal*_*cal 3 java swing event-dispatch-thread
在运行Swing程序的过程中,是否首先生成了UI线程(事件派发线程,EDT)?据推测,任何给定的JVM都可以做任何想做的事情(例如,在启动时始终产生EDT,无论是否曾经使用过),但实际上EDT通常是在什么时候创建的?
首次调用SwingUtilities.invokeLater()时是否会创建它?首次实例化JPanel时?如果事件泵与创建EDT分开启动,那么这种情况何时会发生?
在查看代码之后,似乎它"懒洋洋地初始化",意味着它在需要时尽快初始化,如果尚未初始化的话.在这种情况下,只要有任何事件发布到它的队列中.
这是完整的故事:
在EventDispatchThread被包裹内EventQueue.每个EventQueue都有自己的EDT:
/**
* Just a summary of the class
*/
public class EventQueue {
private static final int ULTIMATE_PRIORITY = 3;
private static final int NUM_PRIORITIES = ULTIMATE_PRIORITY + 1;
private Queue[] queues = new Queue[NUM_PRIORITIES];
private EventQueue nextQueue;
private EventQueue previousQueue;
private EventDispatchThread dispatchThread;
}
Run Code Online (Sandbox Code Playgroud)
的dispatchThread是使用包私有方法初始化initDispatchThread():
final void initDispatchThread() {
pushPopLock.lock();
try {
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
dispatchThread = AccessController.doPrivileged(
new PrivilegedAction<EventDispatchThread>() {
public EventDispatchThread run() {
EventDispatchThread t =
new EventDispatchThread(threadGroup,
name,
EventQueue.this);
t.setContextClassLoader(classLoader);
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(false);
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
return t;
}
}
);
dispatchThread.start();
}
} finally {
pushPopLock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
在检查对此方法的引用之后,有3个地方调用此方法:
EventQueue#wakeup(boolean)EventQueue#postEventPrivate(AWTEvent)(由公共方法调用EventQueue#postEvent(AWTEvent))中EventQueue#createSecondaryLoop(Conditional, EventFilter, long).initDispatchThread()调用之前,dispatchThread检查确保它尚未初始化.有几种方法可以在JDK中查看类的完整源代码(最简单的是附加源代码); 如果您真的感兴趣,请查看这些方法.
所以现在我们知道EventQueue包含线程,并且只要实际需要(事件被发布)就创建线程.是时候谈谈这个队列的位置以及与之通信的方式.
如果你检查代码EventQueue#invokeLater(Runnable)(由它的SwingUtilities对应方调用),你会看到它调用Toolkit.getEventQueue().postEvent(...).这告诉我们队列位于Toolkit.
在Toolkit课堂上,我们可以看到它是在我们呼唤它的时候创建的(如果还没有).它使用反射来创建对象:
public static synchronized Toolkit getDefaultToolkit() {
if (toolkit == null) {
try {
java.lang.Compiler.disable();
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
String nm = null;
Class<?> cls = null;
try {
nm = System.getProperty("awt.toolkit");
try {
cls = Class.forName(nm);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
try {
cls = cl.loadClass(nm);
} catch (ClassNotFoundException ee) {
throw new AWTError("Toolkit not found: " + nm);
}
}
}
if (cls != null) {
toolkit = (Toolkit)cls.newInstance();
if (GraphicsEnvironment.isHeadless()) {
toolkit = new HeadlessToolkit(toolkit);
}
}
} catch (InstantiationException e) {
throw new AWTError("Could not instantiate Toolkit: " + nm);
} catch (IllegalAccessException e) {
throw new AWTError("Could not access Toolkit: " + nm);
}
return null;
}
});
loadAssistiveTechnologies();
} finally {
// Make sure to always re-enable the JIT.
java.lang.Compiler.enable();
}
}
return toolkit;
}
Run Code Online (Sandbox Code Playgroud)
Toolkit是一个抽象类.我们不是实例化这个类的对象,而是创建Toolkit子类的实例:SunToolkit.我们需要知道这一点以查看队列的创建位置.
一旦我们拥有了Toolkit,我们就可以使用它来访问它的EventQueue Toolkit#getSystemEventQueue().这个望远镜采用受保护的抽象方法getSystemEventQueueImpl().我们必须检查子类以查看此方法的实现.在SunToolkit类中,我们有:
protected EventQueue getSystemEventQueueImpl() {
return getSystemEventQueueImplPP();
}
// Package private implementation
static EventQueue getSystemEventQueueImplPP() {
return getSystemEventQueueImplPP(AppContext.getAppContext());
}
public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
EventQueue theEventQueue = (EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY);
return theEventQueue;
}
Run Code Online (Sandbox Code Playgroud)
(EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY)队列来自appContext工具包.现在我们要做的就是找到将队列添加到应用程序上下文的位置:
public SunToolkit() {
Runnable initEQ = new Runnable() {
public void run() {
EventQueue eventQueue;
String eqName = System.getProperty("AWT.EventQueueClass", "java.awt.EventQueue");
try {
eventQueue = (EventQueue) Class.forName(eqName).newInstance();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Failed loading " + eqName + ": " + e);
eventQueue = new EventQueue();
}
AppContext appContext = AppContext.getAppContext();
appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue); //queue added here
PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
}
};
initEQ.run();
}
Run Code Online (Sandbox Code Playgroud)
快速概述:
Toolkit.getDefaultToolkit(),或者每当程序的另一部分(例如向队列发布数据的Swing组件)调用它时)如果您对此有任何疑问,请与我们联系
| 归档时间: |
|
| 查看次数: |
247 次 |
| 最近记录: |