EDT、异步、同步

EDT, asynchronous, synchronous

从EDT(Event Dispatcher Thread)开始一个新线程时,新线程永远不会是EDT,因为只有一个EDT,对吧?我问是因为我看到一些代码检查 if (!SwingUtils.isDispatcherThread()),我想知道为什么它需要这个检查?

我的问题是:当启动一个新线程时,是什么让它同步(必须等待新线程完成)或异步(新线程returns 立即完成)?据此如何自己启动一个同步或异步线程?

以下面为例。在 EDT 中启动非 EDT 线程时,如下所示:

public void actionPerformed(final ActionEvent e)
{
    final Runnable runnable = new Runnable()
    {
      @Override
      public void run()
      {
        //do some non-gui task. The task is not long-running, but 
        //could be blocked
        doTask();       
      }
    }; 

    new Thread(runnable).start();
  }
});

从 EDT 生成的非 EDT 线程是同步的还是异步的?如果 doTask() 挂起,是否应该阻止 EDT UI?

如果我无法控制doTask()并且无法更改方法,那么有什么好的方法来处理产生新线程并且新线程可能挂起的情况?在父线程中使用 Thread.join()?

the new thread will never be EDT, as there is only one EDT, right?

没错。

I am asking as I see some code checks "if (!SwingUtils.isDispatcherThread())", and I wonder why it needs this check?

因为有时可以从 EDT 或后台线程调用方法,并且必须根据当前线程采取不同的操作。

when starting a new thread, what makes it synchronous (has to wait for the new thread to finish) or asynchronous (the new thread returns right away)?

当您启动一个新线程时,新线程总是与生成线程同时运行。除非您明确加入(或使用其他同步机制),否则生成线程永远不会等待生成线程完成。

Should EDT UI be blocked if doTask() hangs?

否,除非生成的线程在保持 EDT 尝试获取的锁时挂起。

If I have no control over doTask() and the method cannot be changed, what is a good way to deal with the situation that spawns a new thread and the new thread might hang? use Thread.join() in parent thread?

那会更糟:现在 EDT 也会挂起,从而完全冻结 UI,直到挂起的线程停止挂起并终止。

如果您有一个挂起的线程,请修复它正在执行的代码,使其不再挂起。如果您无法修复它,请让负责该代码的人来修复它。

  1. EDT:是的,只有 1 个 EDT。您创建的任何线程都不会是 EDT
  2. 同步 vs 异步:java 中的 Thread 与其他任何一个 class 一样,但是当您调用 start() 时,它会创建一个新线程来运行run() 方法或在 Runnable.run 方法中,如果 Runnable 是异步提供的。
  3. 方法可能会阻塞/从不return:关键是使用回调/侦听器...在导致更新的处理过程中的某个时刻调用的方法。没有停止阻塞线程的通用解决方案,但是可以在许多情况下使用的 2 种机制是 (a)InputStream/Reader.close() 如果您正在等待输入流上的数据或 reader,或 (b) Thread.interrupt