---------------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 运维常用命令

    创建生产环境数据库并执行迁移 $ RAILS_ENV=production rake db:create$ RAILS_ENV=production rake db:migrate RAILS_ENV ...

  2. Python decorator @property

    @property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性 下面的链接很好的阐述了@property的概念和应用 http: ...

  3. dojo 官方翻译 dojo/domReady 版本1.10

    官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/domReady.html#dojo-domready dom加载完成后,执行. requi ...

  4. Docker dockerfile命令详解

    docker-file 官网文档:https://docs.docker.com/v17.09/engine/reference/builder/ 制作Dockerfile为Docker入门学习的第一 ...

  5. Centos安装ntfs

    ntfs优盘插在Linux上是无法直接使用的,需要安装ntfs插件才可使用 centos上安装ntfs-3g 下载ntfs-3g安装包,上传至需要安装的服务器并解压 cd 进入ntfs-3g目录,依次 ...

  6. Outlook 2010打开没反应,只有任务栏有图标的解决方法

    Outlook 2010打开没反应,任务栏图标显示如下: 解决方法: 按下Windows+R键,输入regedit: 按回车: 请在注册表编辑器中定位到以下键值,重命名以下4项(比如将outlook重 ...

  7. python第三篇:python、flask关系映射

    python中关系映射主要包括三种:一对多关系映射.一对一关系映射.多对多关系映射. 一对多关系映射 一方:Student(学生) 添加关联属性和反向引用 多方:Article(文章) 添加外键关联 ...

  8. Thinkphp跨模块调用视图文件

    当需要跨模块调用视图文件时,需要使用被包含文件的完整路径,如: <include file="./App/Home/View/Store/header.html"/> ...

  9. Spring MVC工作原理(好用版)

    Spring MVC工作原理 参考: SpringMVC工作原理 - 平凡希 - 博客园https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC的 ...

  10. Python with MYSQL - sytax problem

    Con= MySQLdb.connect(host=',db='test') cur=Con.cursor() cur.execute('insert into staff_daily(Date,Na ...