java 你如何使用事件调度线程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7896723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you use the Event Dispatch Thread?
提问by Tharwen
I learned about how swing isn't thread-safe. Delving deeper, I discovered that every modification to a swing component must be done on the Event Dispatch Thread in order to prevent various issues associated with multithreading. However, the information seemed to completely stop there. There doesn't seem to be a good tutorial that explains how to do this anywhere accessible on the internet.
我了解了 Swing 不是线程安全的。深入研究后,我发现对 Swing 组件的每次修改都必须在 Event Dispatch Thread 上完成,以防止与多线程相关的各种问题。然而,信息似乎完全停在了那里。似乎没有一个很好的教程来解释如何在 Internet 上可访问的任何地方执行此操作。
Patching together information from code posted in relation to other issues, it seemed that I would have to put an untidy block of code around every single swing modification in my program (like this example from my own code):
从发布的与其他问题相关的代码中修补信息,似乎我必须在我的程序中的每个摆动修改周围放置一个不整洁的代码块(就像我自己代码中的这个示例):
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setTitle("Frame title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(800, 480);
setLocationRelativeTo(null);
setIconImage(Toolkit.getDefaultToolkit().createImage(ClassLoader.getSystemResource("Frame icon.png")));
}
});
} catch (Exception e) {
e.printStackTrace();
}
Basically, is this right? Do I have to put that code (or the equivalent with invokeLater) around every modification to a Swing component in my code?
基本上,这是对的吗?我是否必须将该代码(或与 invokeLater 等效的代码)放在对代码中 Swing 组件的每次修改中?
Also, why doesn't Swing do this automatically?
另外,为什么 Swing 不自动执行此操作?
采纳答案by Bill K
The trick is that when swing calls you it will ALWAYS be in the EDT, so you don't have to worry about it.
诀窍是,当摇摆叫你时,它总是在 EDT 中,所以你不必担心。
However if you are in a timer or an action triggered by some other external event, your main thread or any other thread you've created then yes, you have to use invokeLater or invokeAndWait.
但是,如果您在计时器或由其他外部事件、主线程或您创建的任何其他线程触发的操作中,那么是的,您必须使用 invokeLater 或 invokeAndWait。
In other words, yes swing does do "it" automatically. Needing to use invokeXx is so rare that if swing were to do it internally it would waste too much time.
换句话说,yes swing 会自动执行“它”。需要使用 invokeXx 非常罕见,如果 Swing 在内部使用它会浪费太多时间。
Many java programmers never figure this out and it can cause some pretty nasty hard-to-find problems with drawing your GUI. I do wish swing threw an exception when you called it not using the EDT--Java would have a better reputation when it came to professional GUIs if it did because there would be less crap out there.
许多 Java 程序员从来没有弄清楚这一点,它可能会导致绘制 GUI 时出现一些非常讨厌且难以发现的问题。我确实希望当你不使用 EDT 调用它时,swing 会抛出一个异常——如果这样做的话,Java 在专业 GUI 方面会有更好的声誉,因为那里的废话会更少。
回答by ratchet freak
note that any code executed from event handlers is already run in the EDT (the Event in the acronym)
请注意,从事件处理程序执行的任何代码都已经在 EDT 中运行(首字母缩写词中的事件)
this means that for general use (while you don't mess with swingworkers and threadpools and such) you are always inside the EDT
这意味着对于一般用途(虽然你不会弄乱swingworkers和threadpools等)你总是在EDT里面
and you can always query if you are in the EDT with SwingUtilities.isEventDispatchThread()
您可以随时查询您是否在 EDT 中 SwingUtilities.isEventDispatchThread()
also note that in your code the call to invokeAndWait
will fail and throw an error when you are in the EDT already
还要注意,在您的代码中,invokeAndWait
当您已经在 EDT 中时,调用将失败并抛出错误
回答by Savvas Dalkitsis
Not all your UI code must be part of a runnable in an invokeLater call. That is simply because a large part of your program will be run on the EDT anyway. You need to dispatch messages to the EDT only when you are on a different thread.
并非所有 UI 代码都必须是 invokeLater 调用中可运行的一部分。这仅仅是因为您的程序的很大一部分无论如何都将在 EDT 上运行。仅当您在不同的线程上时才需要将消息发送到 EDT。
回答by Zaki
Basically, you dont draw or update the GUI from outside of the EDT. You use SwingUtilitis.invokeLater() from another thread to ensure the GUI drawing or updating code is run on the EDT.
基本上,您不会从 EDT 外部绘制或更新 GUI。您从另一个线程使用 SwingUtilitis.invokeLater() 来确保 GUI 绘图或更新代码在 EDT 上运行。