javax.swing

提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所有平台上的工作方式都相同。

(1)swing:https://baike.so.com/doc/6758892-10428879.html
(2)swing之eventqueue简介:http://www.360doc.com/content/12/1022/01/820209_242886827.shtml
(2)awt:https://baike.so.com/doc/6948659-7171054.html
(3)使用eventqueue.invokelater的好处:http://blog.csdn.net/sinolzeng/article/details/41979681
(4)Java中为什么使用EventQueue.invokeLater:http://blog.csdn.net/qq_15037231/article/details/69102297
(5)在java里actionPerformed(ActionEvent e)是做什么用的?:https://baike.1688.com/doc/view-d26161042.html
(6)【Java线程】Swing事件分发线程EDT与SwingUtilities.invokeLater:http://blog.csdn.net/vking_wang/article/details/8992463

()->语句
相当于:
new Runnable() {
        public void run() {
                try {
                    语句
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
}

线程的工作原理

首先要明白线程的工作原理,jvm有一个main memory,而每个线程有自己的working memory,一个线程对一个variable进行操作时,都要在自己的working memory里面建立一个copy,操作完之后再写入main memory。多个线程同时操作同一个variable,就可能会出现不可预知的结果。

什么是线程安全?线程安全是怎么完成的(原理)?

(1)线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。

(2)在多线程环境中,当各线程不共享数据的时候,那么一定是线程安全的。问题是这种情况并不多见,在多数情况下需要共享数据,这时就需要进行适当的同步控制了。

(3)线程安全一般都涉及到synchronized 就是一段代码同时只能有一个线程来操作 不然中间过程可能会产生不可预制的结果。

(4)如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

什么是线程不安全?

举例 比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1; 而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。 那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。

在Java中Swing是线程不安全的,是单线程的设计

Java Swing是一个单线程图形库,里面的绝大多数代码不是线程安全(thread-safe)的,看看Swing各个组件的API,你可以发现绝大多数没有做同步等线程安全的处理,这意味着它并不是在任何地方都能随便调用的。
只能从事件派发线程访问将要在屏幕上绘制的Swing组件

使用eventqueue.invokelater()好处、原因

EventQueue.invokeLater(new Runnable() {
        public void run() {
                try {
                Array1 frame = new Array1();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
       }
});

Runnable()方法的作用是:标记 其里面的代码 是由线程来执行的。
好处是显而易见的,这个方法调用完毕后,它会被销毁,因为匿名内部类是作为临时变量存在的,给它分配的内存在此时会被释放。这个对于只需要在一个地方使用时可以节省内存,而且这个类是不可以被其它的方法或类使用的,只能被EventQueue.invokeLater()来使用。但如果你需要一个在很多地方都能用到的类,而不是只在某一个类里面或者方法里用的话,定义成匿名内部类显然是不可取的,swingutilities可以解决这个问题。
swingutilities.invokelater()和eventqueue.invokelater(),后者可以不干扰到事件分发线程SwingUtilities版只是一个薄薄的封装方法,它直接转而调用 EventQueue.invokeLater。因为Swing框架本身经常调用SwingUtilities,使用SwingUtilities可以减少程序引入的类。

为什么要用SwingUtilities.invokeLater,而不直接调用呢?

因为大多数SwingAPI是非线程安全的,也就是说不能在任意地方调用,它应该只在EDT中调用。Swing的线程安全靠事件队列和EDT来保障。

Swing程序中的线程

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

(1)初始化线程(Initial Thread)
(2)UI事件调度线程(EDT,Event Dispatch Thread,事件分发线程)
(3)任务线程(Worker Thread)

初始化线程:

每个程序必须有一个main方法,这是程序的入口。该方法运行在初始化或启动线程上。初始化线程读取程序参数并初始化一些对象。在许多Swing程序中,该线程主要目的是启动程序的图形用户界面(GUI)。创建UI的点,也就是程序开始将控制权转交给UI时的点。一旦GUI启动后,对于大多数事件驱动的桌面程序来说,初始化线程的工作就结束了。

EDT线程(必须通过EDT刷新组件):

Swing程序只有一个EDT,该线程负责GUI组件的绘制和更新,通过调用程序的事件处理器响应用户交互。所有事件处理都是在EDT上进行的,程序同UI组件和其基本数据模型的交互只允许在EDT上进行,所有运行在EDT上的任务应该尽快完成,以便UI能及时响应用户输入。EDT会永不间断地徘徊在处理请求与等待请求之间
下图是Swing事件队列的实现机制:

awt是单线程模式的,所有awt的组件只能在(推荐方式)事件处理线程中访问,从而保证组件状态的可确定性。

任务线程:

耗时操作应放到独立的任务线程中,通过SwingWorker启动。

invokeLater和invokeAndWait

由于Swing自身不是线程安全,如果你在其他线程访问和修改GUI组件,那么你必须要使用SwingUtilities. invokeAndWait(runnable), SwingUtilities. invokeLater(runnable)。也就是说对非EDT的并发调用需通过invokeLater()和invokeAndWait()使请求插入到队列中等待EDT去执行
(1)invokeLater(runnable)方法是异步的,它会立即返回,具体何时执行请求并不确定,所以命名invokeLater是稍后调用。
(2)invokeAndWait(runnable)方法是同步的,它被调用结束会立即block当前线程(调用invokeAndWait的那个线程)直到EDT处理完那个请求。invokeAndWait一般的应用是取得Swing组件的数据。
invokeAndWait有非常重要的一条准则是:它不能在EDT中被调用,否则程序会抛出Error,请求也不会去执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值