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

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

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

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

目录
相关文章
|
1月前
|
存储 Java 数据库
如何处理线程池关闭时未完成的任务?
总之,处理线程池关闭时未完成的任务需要综合考虑多种因素,并根据实际情况选择合适的处理方式。通过合理的处理,可以最大程度地减少任务丢失和数据不一致等问题,确保系统的稳定运行和业务的顺利开展。
119 64
|
1月前
|
消息中间件 监控 Java
线程池关闭时未完成的任务如何保证数据的一致性?
保证线程池关闭时未完成任务的数据一致性需要综合运用多种方法和机制。通过备份与恢复、事务管理、任务状态记录与恢复、数据同步与协调、错误处理与补偿、监控与预警等手段的结合,以及结合具体业务场景进行分析和制定策略,能够最大程度地确保数据的一致性,保障系统的稳定运行和业务的顺利开展。同时,不断地优化和改进这些方法和机制,也是提高系统性能和可靠性的重要途径。
119 62
|
25天前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
53 12
|
19小时前
|
安全 Java 容器
【JaveEE】——多线程中使用顺序表,队列,哈希表
多线程环境下使用ArrayList(同步机制,写时拷贝),使用队列,哈希表(高频)ConcurrentHashMap(缩小锁粒度,CAS,扩容优化)
|
2月前
|
并行计算 JavaScript 前端开发
单线程模型
【10月更文挑战第15天】
|
1月前
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
61 7
|
1月前
|
消息中间件 存储 安全
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
25 1
|
2月前
|
安全 调度 C#
STA模型、同步上下文和多线程、异步调度
【10月更文挑战第19天】本文介绍了 STA 模型、同步上下文和多线程、异步调度的概念及其优缺点。STA 模型适用于单线程环境,确保资源访问的顺序性;同步上下文和多线程提高了程序的并发性和响应性,但增加了复杂性;异步调度提升了程序的响应性和资源利用率,但也带来了编程复杂性和错误处理的挑战。选择合适的模型需根据具体应用场景和需求进行权衡。
|
3天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
12 1