Java 线程如何与 invokeLater() 同步?

发布于 2024-11-27 15:02:26 字数 476 浏览 2 评论 0原文

我有一个非 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对岸观火 2024-12-04 15:02:26

代替使用

javax.swing.SwingUtilities.invokeAndWait(Runnable doRun);

导致 doRun.run() 在 AWT 事件上同步执行
调度线程。此调用将阻塞,直到所有挂起的 AWT 事件都已完成
已处理,然后 doRun.run() 返回。

Use

javax.swing.SwingUtilities.invokeAndWait(Runnable doRun);

instead.

Causes doRun.run() to be executed synchronously on the AWT event
dispatching thread. This call blocks until all pending AWT events have
been processed and (then) doRun.run() returns.

春风十里 2024-12-04 15:02:26

我建议您分享 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.

轮廓§ 2024-12-04 15:02:26

好吧,如果您有权访问它,您始终可以将该特定逻辑移出 Swing 线程并移至调用 invokeLater 的线程上。假设 IBM622GUI 的构造函数表现良好,那么在 Swing 线程之外执行您正在执行的操作并没有什么不安全的地方。

除此之外,您还可以利用各种其他机制。

  1. 你可以使用 invokeAndWait,正如 cgull 比我说的那样。
  2. 您可以让可运行对象设置 Future 的值,而不是直接引用,并通过调用 future 的 get 方法来阻止主线程。
  3. 您可以在主线程上使用一个起始计数为 1 的 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 for IBM622GUI is well behaved.

Other than that, you could make use of various other mechanisms.

  1. You could use invokeAndWait, as cgull beat me to saying.
  2. You could have the runnable set the value of a Future instead of a direct reference, and block on the main thread by calling the future's get method.
  3. You could have a CountDownLatch with a starting count of 1 which you await() on your main thread, and countDown() from the Swing thread.

There are many, many utilities to help with synchronization.

飘落散花 2024-12-04 15:02:26

通常,您将参数传递给线程。在后台运行逻辑。然后使用 SwingUtilities.invokeLater() 发回您需要对任何这些对象或 UI 线程上的 UI 元素进行的任何修改。通常,我会创建一个简单的实用程序,允许我指定应在后台线程上运行的内容以及应在 UI 线程上运行的内容。 SwingWorker 是你可以使用的东西,尽管我发现它使用起来非常痛苦。像这样简单的事情:

new AsyncThread<Param,T>() {
   public T executeInBackground( Param param ) {
      // do something long running
      T result = // do something long running;
      return T;
   }

   public void executeOnUI( T result ) {
      // update the UI here, or modify the model, etc.
   }
}.execute( param );

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:

new AsyncThread<Param,T>() {
   public T executeInBackground( Param param ) {
      // do something long running
      T result = // do something long running;
      return T;
   }

   public void executeOnUI( T result ) {
      // update the UI here, or modify the model, etc.
   }
}.execute( param );

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文