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 事件队列

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

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

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

目录
相关文章
|
7天前
|
安全
python_threading多线程、queue安全队列
python_threading多线程、queue安全队列
14 2
|
2月前
|
存储 算法 Java
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
87 0
|
2天前
|
NoSQL Redis
Redis 线程模型
Redis 线程模型
|
3天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
7天前
|
存储 安全 Java
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列
|
9天前
|
Java Linux
【linux线程(三)】生产者消费者模型详解(多版本)
【linux线程(三)】生产者消费者模型详解(多版本)
|
26天前
|
Java Spring
定时任务里面的任务多线程操作
该内容是关于Spring Boot中配置异步任务和定时任务的代码示例。首先通过`@Configuration`和`@EnableAsync`开启异步支持,然后定义线程池,如使用`ThreadPoolExecutor`并设置核心线程数、最大线程数等参数。接着,在需要异步执行的方法上添加`@Async`注解。此外,通过`@EnableScheduling`开启定时任务,并使用`@Scheduled`定义具体任务和执行周期。若需指定多个线程池,可以创建不同的`Executor` bean,并在`@Async`中指定线程池名称。
19 2
|
2月前
|
安全 Java 调度
【C/C++ 线程池设计思路 】设计与实现支持优先级任务的C++线程池 简要介绍
【C/C++ 线程池设计思路 】设计与实现支持优先级任务的C++线程池 简要介绍
48 2
|
3天前
|
缓存 安全 Java
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
|
3天前
|
数据采集 安全 Java
Python的多线程,守护线程,线程安全
Python的多线程,守护线程,线程安全