java并发编程实践学习(9)GUI应用程序

为了维护安全,某一个任务必须运行在Swing的事件线程中。但是你不能在事件线程中执行耗时操作,以免UI失去响应。而且Swing的数据结构不是线程安全的所以你必须小心的把他们限制在事件线程中。
几乎所有的GUI工具集都是单线程化的子系统,意味着所有GUI的活动都被限制在一个单独的线程中。

一.为什么GUI是单线程化的

现代的GUI框架使用了一个模型:模型创建了一个专门的事件发派线程来处理GUI事件。多线程的GUI框架尤其容易造成死锁的影响。

1.顺序处理事件

因为只有唯一一个线程在处理GUI任务,所以他会依次处理GUI任务-一个任务完成后才开始下一个。顺序任务不利的一面是如果一个任务执行要花费的时间长,其他任务也要等到它结束。

2.Swing中的线程限制

所有的Swing组件(比如Jbutton)和数据模型(TableModel)都被限制于事件线程中。GUI对象不用同步,仅仅靠线程限制来保持一致性。这样有利于运行事件的任务不必担心同步的问题;但是你无法从事件之外的地方访问表现对象。

Swing的单线程规则:Swing的组件和模型只能在事件分派的线程中被创建、修改和请求。

单线程规则中还有一些特例,它们可以安全的被任意线程调用:

  • SwingUtilities.isEventDispatchThread,他用来判断当前线程是否是事件线程。
  • SwingUtilities.invokeLater,它可以安排一个Runnable任务在事件线程中执行(可以从任意线程调用)。
  • SwingUtities.invokeAndWait,它可以安排一个Runnable任务在事件线程中执行,并且会阻塞当前线程直到它完成(只能在非GUI线程中调用)
  • 用于将一个repaint或revalidation请求插入到队列的方法集(可以从任意线程调用)
  • 最后用于添加或移除监听器的方法集(可以被任意线程调用,但是监听器一定在事件线程中调用)

Swing可以看成一个单线程化的Executor,它执行事件队中的任务,与线程池一样,有时一个线程死亡的工作者会被另一个新的取代。

二.短期GUI任务

为了简单起见,短期任务可以把全部动作留在时间线程中完成,对于耗时的任务应该将一些工作复核分压到另一个线程中。
这里写图片描述这里写图片描述

三.耗时GUI任务

成熟的GUI应用可能会执行耗时的任务。这些任务必须在另外的线程中运行,而使GUI在它们运行中可以做出响应。

1.取消

任何一个在线程中运行了足够长时间的任务都可能消耗用户大量时间,因此用户可能希望取消它。你可以使用线程中断进行取消,不过更简单的办法是使用Future。

2.进度完成表示符

FutureTask中有一个done钩子函数,可以方便任务完成后的通知,后台Callable完成后会调用done。

3.SwingWorker

在Swing中,取消息、完成消息通知、以及进度指示都是由SwingWorker类提供的、

四.共享数据类型

Swing表现对象(TableModel、TreeModel这些数据模型)是被限制在事件线程中的。在简单的GUI程序中、所有的可变对象都保存在表现对象中,事件线程之外唯一的线程就是主线程。强制这些遵守单线程的规则很容易:不要在主线程中访问数据模型或表现组件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值