---------------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

 
 

 
 

工程结构目录如下:

 
 

 
 

 
 

 
 

BadDemo.java:

 
 

package com.siwuxie095.swingthread;

 
 

import javax.swing.JFrame;

 
 

/**

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

*

* @author siwux

*

*/

 
 

public class BadDemo {

 
 

public static
void main(String[] args) {

 

JFrame frame=new JFrame();

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

frame.setSize(500,200);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

 
 

}

 
 

 
 

 
 

GoodDemo.java:

 
 

package com.siwuxie095.swingthread;

 
 

import javax.swing.JFrame;

import javax.swing.SwingUtilities;

 
 

/**

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

*

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

*

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

*

* @author siwux

*

*/

 
 

public class GoodDemo {

 

public static
void main(String[] args) {

 

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

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

SwingUtilities.invokeLater(new Runnable() {

 

@Override

public
void run() {

JFrame frame=new JFrame();

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

frame.setSize(500,200);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

});

}

 
 

}

 
 

 
 

 
 

NewFrame.java:

 
 

package com.siwuxie095.swingthread;

 
 

import java.awt.BorderLayout;

import java.awt.EventQueue;

 
 

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.border.EmptyBorder;

 
 

//NewFrame 直接继承自 JFrame

public class NewFrame extends JFrame {

 
 

private JPanel contentPane;

 
 

/**

* Launch the application.

*

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

*/

 

public static
void main(String[] args) {

EventQueue.invokeLater(new Runnable() {

public
void run() {

try {

NewFrame frame = new NewFrame();

frame.setVisible(true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

 
 

/**

* Create the frame.

*/

public NewFrame() {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setBounds(100, 100, 450, 300);

contentPane = new JPanel();

contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

contentPane.setLayout(new BorderLayout(0, 0));

setContentPane(contentPane);

}

 
 

}

 
 

 
 

 
 

对比 BadDemo.java 和 GoodDemo.java:

 
 

虽然效果一样,但不能在主线程中直接创建
UI
元素 或 更改
UI
属性,这是线程不安全的

 
 

而使用
SwingUtilities.invokeLater()
方法,在其中创建窗体和设定属性就是线程安全的

 
 

 
 

 
 

对比
GoodDemo.java 和 NewFrame.java:

 
 

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

 
 

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

 
 

 
 

 
 

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

 
 

 
 

 
 

SwingUtilities
属于
javax.swing.SwingUtilities
类,

而
EventQueue
属于
java.awt.EventQueue
类

 
 

二者作用完全相同

 
 

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

 
 

 
 

 
 

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

 
 

 
 

 
 

 
 

 
 

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

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

主方法代码剪切过去

 
 

 
 

 
 

 
 

 
 

 
 

【made by siwuxie095】

主线程与UI线程简介的更多相关文章

  1. C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它

    C# 委托 / 跨线程访问UI /  线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...

  2. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  3. [Android学习笔记]子线程更新UI线程方法之Handler

    关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...

  4. OkHttp3几个简单的例子和在子线程更新UI线程的方法

    okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...

  5. Android ActivityThread(主线程或UI线程)简介

    1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...

  6. C#用副线程改主线程(UI线程)的控件属性的方法(包括Winform和WPF)

    C#用副线程去试图修改主线程的UI控件会报出异常,解决方案是使用副线程注册事件通知主线程自己去修改UI控件 在winform中,方法如下 private void button1_Click(obje ...

  7. C#中后台线程和UI线程的交互

    在C#中,从Main()方法开始一个默认的线程,一般称之为主线程,如果在这个进行一些非常耗CPU的计算,那么UI界面就会被挂起而处于假死状态,也就是说无法和用户进行交互了,特别是要用类似进度条来实时显 ...

  8. WPF线程获取UI线程

    WPF中只能是UI线程才可以改变UI控件相关,当采用多线程工作时,可用以下代码获取 UI线程进行操作: App.Current.Dispatcher.Invoke((Action)delegate() ...

  9. C#在非UI线程调用UI线程的控件

    首先需要定义一个委托(delegate): private delegate void delegateSetProcessBarVal(int value); 然后定义一个方法来执行具体的操作: p ...

随机推荐

  1. 阿里云 rails nginx 配置https访问

    1.申请免费型dv ssl证书:https://common-buy.aliyun.com/?spm=a2c4e.11155515.0.0.7zzvOZ&commodityCode=cas#/ ...

  2. Cocos2d-x中手动构造Json::Value

    由于项目需要Json::Value 不是由服务器传送过来,而是自己手动构造. 带数组的json Json::Value items; for(int i=0,i<2;i++) { items[i ...

  3. MySQL中NOT IN语句对NULL值的处理

    与使用in时不同: 在使用in 时: SELECT COUNT(name) FROM CVE WHERE name NOT IN ('CVE-1999-0001', 'CVE-1999-0002'); ...

  4. 是否可以重定向到 WEB-INFO 下的页面?

    redirect的路径一定不能在WEB-INF路径下,因为redirect是相当于用户直接访问了路径,而用户不能访问WEB-INF目录下的文件,只有程序内部转发的时候才能转发到WEB-INF下的JSP ...

  5. C++(五)— 控制保留小数位数

    1.C++中输出指定保留的小数位数. 这里还要注意,每次输出只要设置一次就行了,因为这两个的作用范围是后续对象,而不是仅对后一个对象起作用. #include<iostream> #inc ...

  6. (转)java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)

    java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明);部分资料参考网络资源 1. java向MySQL插入当前时间的四种方式 第一种:将java.util.Date ...

  7. Android简单数据存储SharedPreferences

    SharedPreferences是Android中存储简单数据的一个工具类.可以想象它是一个小小的Cookie,它通过用键值对的方式把简单数据类型(boolean.int.float.long和St ...

  8. visual studio 高级选项及配置

    visual studio 是一款强大的 IDE,所谓 IDE 即是将通过命令行(一系列复杂的参数选项)编译.链接等操作内置到 IDE 的界面按钮处. 为什么新建的工程,可以直接 #include & ...

  9. Agc017_D Game on Tree

    传送门 题目大意 给定一棵树,$1$号节点为根,两个人轮流操作,每次选择一个根节点外的点,删掉它以及它的子树,不能操作者输,求两人均采用最优策略下先手胜利还是后手胜利. 题解 经典问题树上删边游戏,根 ...

  10. Arc066_E Addition and Subtraction Hard

    传送门 题目大意 给定一个加减法的表达式,让你任意的添加合法的括号对,使的表达式最大. 题解 考虑到任意左括号一定加在减号右边,那么对于第一个左括号,与该左括号相邻的只含有加号的子序列的贡献一定为负, ...