gpt4 book ai didi

java - 什么时候创建 Swing UI 线程?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:55:22 25 4
gpt4 key购买 nike

在运行Swing程序的过程中,当UI 线程(事件调度线程,EDT)首先产生?大概任何给定的 JVM 都可以做任何它想做的事(例如,总是在启动时产生 EDT,无论或者它从未被使用过),但作为一个实际问题,当通常创建 EDT 吗?

是否在 SwingUtilities.invokeLater() 时创建首先叫什么? JPanel 何时首次实例化?如果事件泵与创建分开启动美国东部时间,这通常发生在什么时候?

最佳答案

查看代码后,它似乎是“延迟初始化”的,这意味着它会在需要时立即初始化,如果尚未初始化的话。在这种情况下,只要有任何事件发布到它的队列。


这是完整的故事:

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;
}

dispatchThread 使用包私有(private)方法 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();
}
}

检查对该方法的引用后,有 3 个地方调用了该方法:

  1. 在私有(private)方法EventQueue#wakeup(boolean)
  2. 在私有(private)方法EventQueue#postEventPrivate(AWTEvent)中(由公共(public)方法调用EventQueue#postEvent(AWTEvent))
  3. 在包私有(private)方法 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;
}

Toolkit 是一个抽象类。我们没有实例化此类的对象,而是创建了 Toolkit 子类的实例:SunToolkit。我们需要知道这一点才能查看队列的创建位置。

一旦我们有了 Toolkit,我们就可以使用 Toolkit#getSystemEventQueue() 访问它的 EventQueue。这会延伸到 protected 抽象方法 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;
}

(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();
}

快速概览:

  1. EDT 位于 EventQueue 中
  2. EventQueue 位于 Toolkit 中
  3. 队列是在您创建工具包时创建的
  4. 工具包是手动创建的(通过调用 Toolkit.getDefaultToolkit(),或者每当程序的另一部分(例如将数据发布到队列的 Swing 组件)调用它时)<
  5. EDT 是在事件发布到队列时创建的(并且 EDT 尚未运行)

如果您对此有任何疑问,请告诉我

关于java - 什么时候创建 Swing UI 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26317766/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com