---------------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. 每天一个Linux命令(34)grep命令

          grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具 ...

  2. c# 文件IO操作 StreamReader StreamWriter Split 使用

    StreamWriter(String,Boolean) 若要追加数据到该文件中,则为 true:若要覆盖该文件,则为 false. 如果指定的文件不存在,该参数无效,且构造函数将创建一个新文件. 例 ...

  3. 《程序员代码面试指南》第三章 二叉树问题 二叉树按层打印和ZigZag打印

    题目 二叉树按层打印和ZigZag打印 java代码 package com.lizhouwei.chapter3; import java.util.LinkedList; import java. ...

  4. POJ 1183 反正切函数的应用

    H - 反正切函数的应用 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit ...

  5. JAVA中的4种线程池的使用

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  6. linux 压缩和归档

    在linux下有几种压缩方式:gzip.bzip2.xz.zip gzip 压缩文件以.gz结尾, 只能压缩文件,不能压缩目录 用法: gzip:/path/to/somefile   用来压缩,完成 ...

  7. JS正则表达式,记录自己所学所用的内容

    还没接触正则表达式感觉确实有那么点难度,但接触到后自己琢磨了几天也没发现那么难. 现在教教刚学的或者还没接触正则表达式的同学们入入门,一起学习. 正则表达式基本语法 ***************** ...

  8. html基础学习(注意点)

    浏览器会自动地在块级元素(<p><h1>)的前后添加空行 当显示页面时,浏览器会移除源代码中多余的空格和空行.所有连续的空格或空行都会被算作一个空格.需要注意的是,HTML 代 ...

  9. 分享知识-快乐自己:redis集群搭建

    Redis介绍: 1.开源的NoSql数据库 2.C语言编写 3.基于内存运行,并且支持持久化 4.Key value存储 5.是主流的Nosql数据库之一 Redis优点: 1.内存使用方面,表现优 ...

  10. 八 Django框架,模板语言

    模板语言就是可以将动态数据在html模板渲染的语言 一.接收值渲染 locals()函数,写在请求响应render()函数里,可以将逻辑处理函数里的变量传到html用模板语言渲染 {{...}}接收一 ...