请教:这是一种什么用法?

时间:2021-10-12 12:57:05
看到别人写的代码:

EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
       ....
    }
});


看起来像是启动一个线程,并在线程中做一些事情,为什么放在EventQueue.invokeLater中呢?

(为什么不直接创建一个Thread对象)

这是什么意思呢?

这种写法主要用于什么场合呢?

25 个解决方案

#1


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

#2


对于这点我也不是明白

#3


这样是为了防止出现类似于 一个 任务需要大量时间处理时,你的界面不会死掉。

你可以去查下 EventQueue 的工作原理,大概是下面的:

   简单来讲,在EventQueue中有一个dispatchThread,这是个线程类,负责事件的分发,当Queue中有事件的时候,他会摘取前面的事件并分发给相应的对象进行处理,等处理完之后再获取下一个,当Queue中没有事件的时候,线程等待。

    当有事件触发时,系统会调用EventQueue的push方法将AWTEvent添加到EventQueue的最后,同时唤醒dispatchThread。 

    为什么界面会死掉

    所以能看到,Swing的事件分发实际上是同步的,并且都是在dispatchThread这个线程中处理的,也就是说是个事件一个事件处理的,如果有某一个事件处理的时间非常长的时侯,其他事件就会被堵塞在那里,从现象上看得话,就是界面会死掉,如果界面被其他窗口覆盖之后再回到前面的时侯,会变成一片灰色,这是因为PaintEvent被堵塞而不能被分发出去的缘故。

#4


就是个闭包而已

#5


run里的代码会在将来的某个时间被调用

#6


那为什么不用Thread对象呢?

#7


还不是很明白

#8


也可以用thread对象,thread也实现了Runnable接口

#9


该回复于2010-09-30 09:43:30被版主删除

#10


学习了。。

#11


不错,学习中

#12


该回复于2010-09-30 09:53:18被版主删除

#13


lz主的问题其实很简单
在java中并不像别的语言那样能直接传入一个代码块,而是传入一个对象
其中:
EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
       ....
    }
});
的 new Runnable(){run()}只是一种创建对象的简便方式,这样写避免了先创建一个继承Runable接口的
类,然后再创建对象,所以比较简便,在多线程中经常用到。
具体的请看一下面向对象中对面向接口编程的介绍

#14


ls 的理解错了,你说的这种创建对象的简便写法我知道。我现在想问的只是
EventQueue.invokeLater(...)这种写法。这种写法我以前没用过,
我以前用的都是直接创建一个线程对象来做,故请教两者的区别。

#15


学习了

#16


匿名类

#17


学习!

#18


EventQueue.invokeLater

相当于,定义了一个任务,这个任务在将来的某个时刻被awt线程调用执行。
就好比,放学了,老师给你布置个任务。你回家做。

#19


new Runnable() {} 创建一个“可以被执行”的对象,但这个对象具体什么时候开始执行由EventQueue来决定。

通常你所写的new Thread().start()是创建了这个可执行对象,并且开始执行

#20


引用 6 楼 testpwd 的回复:
那为什么不用Thread对象呢?
因为 awt, 或者 swing 为了确保所有的组件是同步的,所以他被设计为单线程的,同一时刻,只有一个线程(事件分发线程,EDT)在操作 组件。所以,要想能正确运行,用户也必须在事件分发线程中操作组件,EventQueue.invokeLater(Runnable),提供了这个方法,让用户的操作在事件分发线程中完成。

#21


其实用Thread类也是可以的,只要你不启动这个Thread,效果和Runnable一样
你可以试一下EventQueue.invokeLater(new Thread() {
    public void run() {
        ....
    }
});

#22


EventQueue定义了一个invokeLater(Runnable instance)方法
调用的时候EventQueue.invokeLater(new Runnable(){public void run(){};})
其中的参数并不是实现创建好的,而是在调用的时候才创建;
也可以EventQueue.invokeLater(runnableInstance);
前提是runnableInstance实现了Runnable接口

#23


引用 4 楼 david2083 的回复:
就是个闭包而已


这叫闭包吗?

#24


匿名内部类,如果一个类对象,它只使用一次的话,可以这样写

#25


节省代码长度,呵呵,学习!

#1


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

#2


对于这点我也不是明白

#3


这样是为了防止出现类似于 一个 任务需要大量时间处理时,你的界面不会死掉。

你可以去查下 EventQueue 的工作原理,大概是下面的:

   简单来讲,在EventQueue中有一个dispatchThread,这是个线程类,负责事件的分发,当Queue中有事件的时候,他会摘取前面的事件并分发给相应的对象进行处理,等处理完之后再获取下一个,当Queue中没有事件的时候,线程等待。

    当有事件触发时,系统会调用EventQueue的push方法将AWTEvent添加到EventQueue的最后,同时唤醒dispatchThread。 

    为什么界面会死掉

    所以能看到,Swing的事件分发实际上是同步的,并且都是在dispatchThread这个线程中处理的,也就是说是个事件一个事件处理的,如果有某一个事件处理的时间非常长的时侯,其他事件就会被堵塞在那里,从现象上看得话,就是界面会死掉,如果界面被其他窗口覆盖之后再回到前面的时侯,会变成一片灰色,这是因为PaintEvent被堵塞而不能被分发出去的缘故。

#4


就是个闭包而已

#5


run里的代码会在将来的某个时间被调用

#6


那为什么不用Thread对象呢?

#7


还不是很明白

#8


也可以用thread对象,thread也实现了Runnable接口

#9


该回复于2010-09-30 09:43:30被版主删除

#10


学习了。。

#11


不错,学习中

#12


该回复于2010-09-30 09:53:18被版主删除

#13


lz主的问题其实很简单
在java中并不像别的语言那样能直接传入一个代码块,而是传入一个对象
其中:
EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
       ....
    }
});
的 new Runnable(){run()}只是一种创建对象的简便方式,这样写避免了先创建一个继承Runable接口的
类,然后再创建对象,所以比较简便,在多线程中经常用到。
具体的请看一下面向对象中对面向接口编程的介绍

#14


ls 的理解错了,你说的这种创建对象的简便写法我知道。我现在想问的只是
EventQueue.invokeLater(...)这种写法。这种写法我以前没用过,
我以前用的都是直接创建一个线程对象来做,故请教两者的区别。

#15


学习了

#16


匿名类

#17


学习!

#18


EventQueue.invokeLater

相当于,定义了一个任务,这个任务在将来的某个时刻被awt线程调用执行。
就好比,放学了,老师给你布置个任务。你回家做。

#19


new Runnable() {} 创建一个“可以被执行”的对象,但这个对象具体什么时候开始执行由EventQueue来决定。

通常你所写的new Thread().start()是创建了这个可执行对象,并且开始执行

#20


引用 6 楼 testpwd 的回复:
那为什么不用Thread对象呢?
因为 awt, 或者 swing 为了确保所有的组件是同步的,所以他被设计为单线程的,同一时刻,只有一个线程(事件分发线程,EDT)在操作 组件。所以,要想能正确运行,用户也必须在事件分发线程中操作组件,EventQueue.invokeLater(Runnable),提供了这个方法,让用户的操作在事件分发线程中完成。

#21


其实用Thread类也是可以的,只要你不启动这个Thread,效果和Runnable一样
你可以试一下EventQueue.invokeLater(new Thread() {
    public void run() {
        ....
    }
});

#22


EventQueue定义了一个invokeLater(Runnable instance)方法
调用的时候EventQueue.invokeLater(new Runnable(){public void run(){};})
其中的参数并不是实现创建好的,而是在调用的时候才创建;
也可以EventQueue.invokeLater(runnableInstance);
前提是runnableInstance实现了Runnable接口

#23


引用 4 楼 david2083 的回复:
就是个闭包而已


这叫闭包吗?

#24


匿名内部类,如果一个类对象,它只使用一次的话,可以这样写

#25


节省代码长度,呵呵,学习!