Java 线程如何与 invokeLater() 同步?
我有一个非 GUI 线程,它使用 IBM1622GUI 的构造函数的一部分启动 JFrame
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cardReadPunchGUI = new IBM1622GUI(); // instantiate
cardReadPunchGUI.setVisible(true);
}
});
为其自身实例化一个“模型”,我的非 GUI 线程需要访问该模型:
cardReadPunch = IBM1622GUI.getModel();
我的非 GUI 线程与新线程同步的正确方法是什么“稍后调用”的 GUI? (当然,如果没有同步,IBM1622GUI.getModel()
只会返回 null。)
I have a non-GUI thread that starts a JFrame using
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
cardReadPunchGUI = new IBM1622GUI(); // instantiate
cardReadPunchGUI.setVisible(true);
}
});
Part of IBM1622GUI's constructor instantiates a "model" for itself, which my non-GUI thread needs access to:
cardReadPunch = IBM1622GUI.getModel();
What is the correct way for my non-GUI thread to synchronize with the new GUI that's been "invoked later"? (Without synchronization, of course, IBM1622GUI.getModel()
just tends to return null.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
代替使用
。
Use
instead.
我建议您分享 CountDownLatch 对于非 GUI 和 GUI 线程都初始化为 1。
非 GUI 线程启动时将调用latch.await(),这会将其置于阻塞状态。
GUI 线程在完成初始化后将调用
latch.countDown()
,之后非 GUI 线程将从等待调用中退出,并且两个线程都会同步。Id suggest you share an CountDownLatch initialized to 1 with both both the non-GUI and GUI threads.
The non GUI thread when it starts will call
latch.await()
which will put it in a blocked state.The GUI thread will call
latch.countDown()
when it finishes its initialization after which the non-GUI thread will exit from the await call and both threads are synchronized.好吧,如果您有权访问它,您始终可以将该特定逻辑移出 Swing 线程并移至调用
invokeLater
的线程上。假设IBM622GUI
的构造函数表现良好,那么在 Swing 线程之外执行您正在执行的操作并没有什么不安全的地方。除此之外,您还可以利用各种其他机制。
invokeAndWait
,正如 cgull 比我说的那样。Future
的值,而不是直接引用,并通过调用 future 的get
方法来阻止主线程。CountDownLatch
并使用await()
,并在 Swing 线程上使用countDown()
。有很多很多实用程序可以帮助同步。
Well, if you have access to it you could always move that particular logic outside of the Swing thread and onto the thread that calls
invokeLater
. There's nothing unsafe about doing what you're doing there off of the Swing thread, assuming the constructor forIBM622GUI
is well behaved.Other than that, you could make use of various other mechanisms.
invokeAndWait
, as cgull beat me to saying.Future
instead of a direct reference, and block on the main thread by calling the future'sget
method.CountDownLatch
with a starting count of 1 which youawait()
on your main thread, andcountDown()
from the Swing thread.There are many, many utilities to help with synchronization.
通常,您将参数传递给线程。在后台运行逻辑。然后使用 SwingUtilities.invokeLater() 发回您需要对任何这些对象或 UI 线程上的 UI 元素进行的任何修改。通常,我会创建一个简单的实用程序,允许我指定应在后台线程上运行的内容以及应在 UI 线程上运行的内容。 SwingWorker 是你可以使用的东西,尽管我发现它使用起来非常痛苦。像这样简单的事情:
AsyncThread 将在另一个线程上执行executeInBackground() 方法。然后在内部它会使用 SwingUtilities.invokeLater() 回发到 UI 线程。然后executeOnUI将在UI线程上运行。 execute() 方法可以创建一个在后台运行的线程,处理异常等。
我会让 GUI 可能启动该线程,并让 GUI 将其模型或它需要的任何部分传递给该线程。而不是相反。这样您就可以让 UI 提供有关正在运行的后台线程的反馈。但是,您不能让后台线程接触(写入/修改/更改)UI 线程也会同时读取/写入的模型成员。因此,如果您计划修改模型以响应后台线程,请将其发布回 UI 线程以确保安全。
Typically you pass parameters to the Thread. Run the logic in the background. And then post back any modifications you need to do to any of those objects, or UI elements on the UI thread using SwingUtilities.invokeLater(). Typically I create a simple a utility that allows me to specify what should run on the background thread, and what should run on the UI thread. SwingWorker is something you could use although I find it extremely painful to use. Something simple like this:
AsyncThread would execute the executeInBackground() method on another thread. Then internally it would post back to UI thread using SwingUtilities.invokeLater(). Then executeOnUI would run on the UI thread. The execute() method could create a thread to run in background, handle exceptions, etc.
I'd let the GUI possibly kick off the thread, and let the GUI pass it's model, or whatever part it needs, to the thread. Instead of the other way around. That way you can have the UI give feedback about that background thread that's running. But, you can't let the background thread touch (write/modify/change) members of that model that the UI thread would be reading/writing too at the same time. So if you plan on modifying the model in response to the background thread, post it back to the UI thread to be safe.