java ui 线程_主线程与UI线程简介

---------------siwuxie095

Java 程序的主线程

当 Java 程序启动时,一个线程立刻运行,该线程通常叫做程序的

主线程(main Thread),因为它是程序开始时就执行的

一般来说,某个类中会有一个

main 函数,当程序启动时,

该函数就会第一个自动得到执行,并成为程序的主线程

主线程的特征如下:

·

主线程是产生其他子线程的线程

·

主线程中执行程序的控制

·

通常主线程必须最后完成执行,因为它执行各种关闭动作

『永远不要在主线程中直接操作界面』

Swing 的 UI 线程

Swing API 的设计目标是强大、灵活和易用

Swing 组件不支持多线程访问,程序要操作 或 更改界面内容,

必须向单一线程执行请求,把这个单一的线程称为事件派发线程

(可简称为

UI 线程)

这意味着

Swing 是线程不安全的,所有对于 UI 元素的修改都必须

提交给

UI 线程执行,不能在主线程 或 其他任何线程中直接操作 UI

的内容

如果要从

UI 线程 或 绘制代码以外的地方 访问 UI,需要使用 SwingUtilities 类

invokeLater() 或 invokeAndWait() 方法

如果要处理一些耗费大量计算能力

I/O 能力限制的工作,可以使用一个

线程工具类,如:SwingWorker 或 Timer

如:

工程名:SwingThreadSafeTest

包名:com.siwuxie095.swingthread

类名:BadDemo.java、GoodDemo.java、NewFrame.java

工程结构目录如下:

0ab377caecdeae3ec5636fc569b86d2b.png

BadDemo.java:

packagecom.siwuxie095.swingthread;

importjavax.swing.JFrame;

/**

*错误,不可以在主线程中创建UI元素或更改UI属性

*

* @author siwux

*

*/

public classBadDemo {

public staticvoidmain(String[] args) {

JFrame frame=newJFrame();

frame.setTitle("这是一个窗口");

frame.setSize(500,200);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

}

GoodDemo.java:

packagecom.siwuxie095.swingthread;

importjavax.swing.JFrame;

importjavax.swing.SwingUtilities;

/**

*虽然效果相同,但窗体的创建和其属性的设定都变成了线程安全的操作

*

* SwingUtilities.invokeLater()的底层实际上就是EventQueue.invokeLater()

*

* EventQueue即事件派发线程,即UI线程

*

* @author siwux

*

*/

public classGoodDemo {

public staticvoidmain(String[] args) {

//在主方法中如果要创建一个新的窗体元素,可以通过静态方法

//调用SwingUtilities类的invokeLater()方法,传入匿名对象new Runnable()

SwingUtilities.invokeLater(newRunnable() {

@Override

publicvoidrun() {

JFrame frame=newJFrame();

frame.setTitle("这是一个窗口");

frame.setSize(500,200);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

});

}

}

NewFrame.java:

packagecom.siwuxie095.swingthread;

importjava.awt.BorderLayout;

importjava.awt.EventQueue;

importjavax.swing.JFrame;

importjavax.swing.JPanel;

importjavax.swing.border.EmptyBorder;

//NewFrame直接继承自JFrame

public classNewFrame extendsJFrame {

privateJPanel contentPane;

/**

* Launch the application.

*

* EventQueue.invokeLater()是窗体创建是自带的方法

*/

public staticvoidmain(String[] args) {

EventQueue.invokeLater(newRunnable() {

publicvoidrun() {

try{

NewFrame frame = newNewFrame();

frame.setVisible(true);

} catch(Exception e) {

e.printStackTrace();

}

}

});

}

/**

* Create the frame.

*/

publicNewFrame() {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setBounds(100, 100, 450, 300);

contentPane = newJPanel();

contentPane.setBorder(newEmptyBorder(5, 5, 5, 5));

contentPane.setLayout(newBorderLayout(0, 0));

setContentPane(contentPane);

}

}

对比 BadDemo.java 和 GoodDemo.java:

虽然效果一样,但不能在主线程中直接创建

UI

元素 或 更改

UI

属性,这是线程不安全的

而使用

SwingUtilities.invokeLater()

方法,在其中创建窗体和设定属性就是线程安全的

对比

GoodDemo.java 和 NewFrame.java:

效果不谈(次要),主要看其主方法中的实现,如下:

GoodDemo.java 使用 SwingUtilities.invokeLater() 方法

d8c57f169cecb4a87069d0d79fec9a2e.png

NewFrame.java 使用 EventQueue.invokeLater() 方法

6f3fcee1b919a0304000e7a3a3012f25.png

SwingUtilities

属于

javax.swing.SwingUtilities

类,

EventQueue

属于

java.awt.EventQueue

二者作用完全相同

「EventQueue

即事件派发线程,也即 UI 线程」

实际上

SwingUtilities.invokeLater()

的底层就是

EventQueue.invokeLater()

2ad3401836f02eb8e55874a1625e5baf.png

5978aff5333e62bef5ab17ed858e6aab.png

一般情况下,如果将窗体创建为一个新的类对象(即类似于这里的

NewFrame.java),

想要在另外一个类中调用,而不在窗体程序中进行调用,可以将窗体程序中自动生成的

主方法代码剪切过去

【made by siwuxie095】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值