我知道“线程”意味着什么,如果我理解事件调度线程(EDT)为 “只是一个线索”,它解释了很多,但显然,它并不能解释一切。
我不明白这个帖子有什么特别之处。例如,我不明白为什么我们应该在EDT中启动GUI?为什么“主”线程适合GUI?好吧,如果我们只是不想占用主线程,为什么我们不能在“另一个线程”中启动GUI为什么它应该是一些叫做EDT的“特殊”线程?
然后我不明白为什么我们不能像任何其他线程一样启动EDT?为什么我们应该使用一些特殊工具(称为invokeLater
)。而且,与其他任何线程不同,GUI不能立即启动。我们应该等到它准备接受我们的工作。是因为EDT可以同时执行多项任务吗?
如果你决定回答这个问题,你是否可以使用一个非常简单的术语,否则,我恐怕无法理解答案。
增加:
我一直以为每个帖子都有一个“任务”。因此,在每个线程中,我们执行预定义的命令序列。但在我看来,在事件调度线程中我们可以拥有服务器任务。好吧,它们不是同时执行的(线程在不同的任务之间切换,但在一个线程中仍然有几个任务)。这样对吗?例如,EDT中有一个显示主窗口的线程,然后另外我们向EDT发送另一个应该更新其中一个窗口组件的任务,EDT将在它准备就绪时执行这个新任务。 EDT是否以这种方式与其他线程不同?
答案 0 :(得分:6)
事件调度线程是处理所有GUI事件并管理Swing GUI的线程。如果您的程序中有任何GUI,它将在Swing代码中的某个位置启动。它在幕后完成的原因是因为简单 - 您不必费心自己启动和管理额外的线程。
关于必须使用invokeLater()
更新GUI的事实,这是因为并发问题。 GUI只能从一个线程修改,因为Swing不是线程安全的(值得注意的是大多数工具包不是线程安全的,有一个nice article给出一些想法为什么)。这就是为什么你必须提交所有GUI更新才能在EDT上运行。
您可以在Sun tutorial on concurrency in Swing中的Swing和事件派发线程中阅读有关并发性的更多信息。此外,如果您想了解如何以不同的方式完成此操作,您可以查看SWT toolkit。在SWT中,您必须自己管理EDT。
答案 1 :(得分:6)
我一直认为我们有一个 每个帖子的“任务”。所以,在每个线程中 我们执行预定义的序列 命令。但在我看来,在 事件调度线程我们可以 有严峻的任务。好吧,他们不是 同时执行(线程 在不同任务之间切换但是 还有几项任务合二为一 线)。这样对吗?例如 EDT中有一个主题 显示主窗口,然后 除此之外,我们发送给了 EDT另一个应该更新的任务 其中一个窗口组件和EDT 每当它执行这个新任务 准备好了。 EDT与其他人不同吗? 以这种方式线程?
不,EDT与其他线程没有根本的区别。并且“任务”不是一个好用的词,因为它可能与OS级进程(通常也称为任务)混淆。更好地使用Runnable
,这是用于通过invokeLater()
向EDT提供代码的接口。
EDT基本上连接到它必须做的事情的队列。当用户单击GUI上的按钮时,通知连接到该按钮的所有侦听器的Runnable
进入队列。调整窗口大小时,执行重新验证和重新绘制的Runnable
会进入队列。当您使用invokeLater()
时,您的Runnable
会进入队列。
EDT只是运行一个无限循环,说“从队列中取出Runnable
(如果它是空的睡眠,直到你被告知它不是)并执行它。
因此,它一个接一个地执行所有那些小Runnable
个代码片段,这样它们每个人在运行时基本上都有自己的GUI,并且不必担心同步任何东西。当您从另一个线程操作GUI时,此假设被破坏,您最终可能会在损坏的状态下使用GUI。
答案 2 :(得分:3)
What is the EDT?
围绕Swing API出现的大量并发问题,这是一个hacky解决方法;)
说真的,很多Swing组件都不是“线程安全的”(一些着名的程序员甚至称为Swing“线程敌对”)。通过拥有一个独特的线程,对这个线程恶意的组件进行所有更新,你就会避免很多潜在的并发问题。除此之外,您还可以保证它将按顺序运行使用invokeLater传递的Runnable。
请注意,这不仅仅是因为你避免了并发问题:你必须尊重Sun关于在EDT上必须做什么和不能做什么的指导方针,否则你会遇到严重的问题应用
另一个好处是,一些Swing组件倾向于抛出不必要的异常,当发生这种情况时,它们会自动处理并且不会使EDT崩溃(如果你真的设法杀死EDT它会自动重启AFAIK)。
换句话说:你不必处理所有破坏的Swing组件以及他们自己抛出的异常:EDT正在处理这个问题(只需看看在Sun的bug游行中抛出异常的无数Swing错误) ,它很吸引人......然而大多数应用程序仍能正常工作)。
此外,通过仅执行EDT中的强制操作,您的应用程序的GUI可以保持“响应”,即使很难,也可能会在后台运行任务。
答案 3 :(得分:3)
要记住的重要一点是Swing类不是线程安全的。这意味着你总是应该从同一个线程调用Swing方法,否则你可能会遇到奇怪或未定义的行为。
所以解决方案:只从单个线程调用Swing方法。这是EDT线程 - 除了它是指定调用swing方法的线程之外,它并不特别。
现在您可能会问为什么Swing方法不是线程安全的?经过几次不成功的尝试,GUI工具包设计者发现设计一个线程安全的GUI工具包本身是不可能的。通常,事件以相反的方向传递(从下到上的输入事件,从上到下的应用程序事件),这总是导致死锁。所以这就是它的方式。