Swing 的任务线程与 EDT 事件分发队列模型(上)

简介: Swing 的任务线程与 EDT 事件分发队列模型(上)

1 现象及问题

在Swing程序中,经常能看到如下这种代码:

image.png

为何用invokeLater,而不直接调用呢?

大多数Swing的API非线程安全,不能在任意地方调用,应该只在EDT中调用。

Swing的线程安全靠事件队列和EDT来保证。

EventQueue的派发机制由单独的一个线程 - 事件派发线程(EDT)管理

Swing将GUI请求放入一个事件队列中执行。通过EDT,使得非线程安全的Swing函数库避开了并发问题。

3 Swing 中的线程分类

一个Swing程序中一般有下面三种类型的线程:

  • 初始化线程(Initial Thread)
  • 每个程序必须有一个main方法作为程序的入口。

该方法运行在初始化或启动线程上。初始化线程读取程序参数并初始化一些对象。

在许多Swing程序中,该线程主要目的是启动程序的GUI。创建UI的点,也就是程序开始将控制权转交给UI时的点。

一旦GUI启动后,对大多数事件驱动的桌面程序,初始化线程的工作就结束了。


UI事件调度线程(EDT)

Swing程序只有一个EDT,负责GUI组件的绘制和更新,调用程序的事件处理器来响应用户交互。

所有事件处理都是在EDT执行,程序同UI组件和其基本数据模型的交互只允许在EDT上进行。

所有运行在EDT上的任务应该尽快完成,以便UI能及时响应用户输入。


任务线程(Worker Thread)

4 Swing 编程铁律

4.1 必须通过EDT刷新组件

从其他线程访问UI组件及其事件处理器会导致界面更新和绘制错误

4.2 禁止在EDT执行其他耗时操作

在EDT上执行耗时任务会使程序失去响应,这会使GUI事件阻塞在队列中得不到处理

4.3 耗时操作放在独立的任务线程

通过SwingWorker启动。应使用独立的任务线程来执行耗时计算或输入输出密集型任务。

  • 比如同数据库通信
  • image.png
  • 访问网站资源、读写大树据量的文件。

任何干扰或延迟UI事件的处理只应出现在独立任务线程中。

  • 在初始化线程(即禁止在main方法中直接创建Frame,在初始化线程中应使用invokeLater初始化GUI)
  • 任务线程同Swing组件或其缺省数据模型进行的交互

都是非线程安全性操作。

通过SwingWorker类的管理,隔离EDT和任务线程,使它们各负其责

  • EDT 绘制和更新界面,并响应用户输入
  • 任务线程,执行和界面无直接关系的耗时任务和I/O密集型操作

5 事件队列

在计算机数据结构中,队列是一个特殊的数据结构。

  • 它是线性的
  • 元素是先进先出的,进入队列的元素必须从末端进入,先入队的元素先得到执行,后入队的元素等待前面的元素执行完毕出队后才能执行,队列的处理方式是执行完一个再执行下一个

队列与线程安全是无关的,不过要想将队列保证线程安全,只需要仿照生产者/消费者模式加上线程的等待/通知即可。

目录
相关文章
|
20天前
|
存储 监控 Java
|
20天前
|
安全 Java 开发者
Swing 的线程安全分析
【8月更文挑战第22天】
28 4
|
19天前
|
安全 Java API
|
11天前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
19 0
|
14天前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
21天前
|
设计模式 安全 前端开发
Swing 是线程安全的吗?
【8月更文挑战第21天】
29 0
|
27天前
|
Cloud Native Java 调度
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
|
15天前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
43 1
|
7天前
|
存储 Ubuntu Linux
C语言 多线程编程(1) 初识线程和条件变量
本文档详细介绍了多线程的概念、相关命令及线程的操作方法。首先解释了线程的定义及其与进程的关系,接着对比了线程与进程的区别。随后介绍了如何在 Linux 系统中使用 `pidstat`、`top` 和 `ps` 命令查看线程信息。文档还探讨了多进程和多线程模式各自的优缺点及适用场景,并详细讲解了如何使用 POSIX 线程库创建、退出、等待和取消线程。此外,还介绍了线程分离的概念和方法,并提供了多个示例代码帮助理解。最后,深入探讨了线程间的通讯机制、互斥锁和条件变量的使用,通过具体示例展示了如何实现生产者与消费者的同步模型。