进程、线程、 Thread类的基本用法 【javaee】

news2025/7/6 20:42:35

目录

一、什么是进程/任务(Process/Task)

二、什么是线程(Thread)

三、进程和线程的区别

四、创建线程的方法:

方法1 继承 Thread ,重写run

 方法2 实现 Runnable 接口

方法3  匿名内部类创建 Thread 子类对象

方法4 匿名内部类创建 Runnable 子类对象

方法5 lambda 表达式创建 Runnable 子类对象

五、如何查看进程中的线程

六、Thread类中的常见构造方法

七、Thread的常见属性​编辑

八、中断线程

方法一:直接自己定义 标志位 

方法二:使用 Thread类 中自带的标志位~ 

九、等待线程 - join() 


一、什么是进程/任务(Process/Task)

        进程是操作系统对一个正在运行的程序的一种抽象,换言之,可以把进程看做程序的一次运行过程。通俗来说,一个跑起来的应用程序就被成为进程。同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位

        为啥要有进程:进程是为了解决并发编程这个问题,现在的CPU都是多核CPU,利用代码要把CPU的多核心充分利用上。

二、什么是线程(Thread)

        一个线程就是一个 "执行流". 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 "同时" 执行着多份代码.

        为啥要有线程:多进程编程已经可以解决很多并发编程的问题了,CPU的很多资源也可以调度起来了。但是,在资源分配和回收上,多进程还是有很多短板。主要有以下三点:

        1.创建一个进程,开销比较大。

        2.销毁一个进程,开销比较大。

        3.调度一个进程,开销也比较大。

         进程消耗资源多,速度慢(创建,销毁,调度),资源分配回收效率低,于是就出现了线程(轻量级进程)解决并发编程的前提下,让创建,销毁,调度的速度快一点,主要是把申请资源/释放资源的操作省下来。

三、进程和线程的区别

  1. 进程是包含线程的. 每个进程至少有一个线程存在,即主线程。
  2. 进程和进程之间不共享内存空间. 同一个进程的线程之间共享同一个内存空间.
  3. 进程是系统分配资源的最小单位,线程是系统调度的最小单位。
  4. 线程模型,天然就是资源共享的,多个线程抢同一个资源,非常容易触发线程安全问题;进程模型,天然就是资源隔离的,不容易触发。进行进程间通信的时候,多个进程访问同一个资源,就可能出现问题

  5. 进程的上下文切换速度比较慢,而线程的上下文切换速度比较快。

  6. 进程都拥有自己独立的虚拟地址空间,有多个进程时,其中一个进程崩溃了并不会影响其他进程。但是线程是多个线程共用一个内存空间,当一个线程抛异常,如果处理不好很可能会把整个进程都给带走了,其他线程也就挂了

注意:

  1. 增加线程数量也不是一直可以提高速度的,CPU核心数量是有限的,线程数量太多开销反而浪费在线程调度上
  2. 系统创建线程也是要消耗资源的,虽然比进程轻量但也不是0,创建太多线程会导致资源耗尽,导致别的进程用不了
  3. 同一个进程里的多个线程之间共用了进程的同一份资源(内存和文件描述符表),只有第一个线程启动时开销是比较大的,后续线程就省事了

Java操作多线程最核心的Thread类,不需要导其他包。java.lang包下最基本的类。

四、创建线程的方法:

 

方法1 继承 Thread ,重写run

1) 继承 Thread 来创建一个线程类

    class MyThread extends Thread{
        @Override
        public void run(){
            System.out.println("hello thread");
        }
    }

 2) 创建 MyThread 类的实例   

MyThread t = new MyThread();

3) 调用 start 方法创建启动线程,新的线程负责执行t.run(); 

 t.start(); // 线程开始运行

 

 t.run();方法重写//虽然t是父类的引用,此处调用的run仍然是子类的方法(t本质上还是指向了子类的对象)

start 和 run 之间的区别

start是真正创建了一个线程,线程是独立的执行流

run只是描述了这个线程要干的活是啥,如果直接在main中调用run,此时没有创建新线程全是main线程一个在工作

 方法2 实现 Runnable 接口

1) 实现 Runnable 接口

class MyRunnable implements Runnable{
    @Override
    public void run(){
        System.out.println("hello thread");
    }
}

2) 创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.

Thread t = new Thread(new MyRunnable());

3) 调用 start 方法创建启动线程,新的线程负责执行t.run(); 

 t.start(); // 线程开始运行

方法3  匿名内部类创建 Thread 子类对象

public class Main {
    public static void main(String[] args) {
        Thread t = new Thread (){
            @Override
            public void run(){
                System.out.println("hello thread");
             }
        };
        t.start();
    }
}
  1. 创建一个Thread的子类(子类没有名字,所以才叫匿名)
  2. 创建了子类的实例,并且让t引用指向该实例

方法4 匿名内部类创建 Runnable 子类对象

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("使用匿名类创建 Runnable 子类对象");
   }
});

和方法二本质相同,只不过是把实现Runnable任务交给匿名内部类的语法

此处创建了一个类,实现Runnable,同时创建了类的实例并且传给Thread的构造方法

方法5 lambda 表达式创建 Runnable 子类对象

Thread t3 = new Thread(() -> System.out.println("使用匿名类创建 Thread 子类对象"));
Thread t4 = new Thread(() -> {
    System.out.println("使用匿名类创建 Thread 子类对象");
});

五、如何查看进程中的线程

可以用jdk自带的工具jconsole查看当前的java进程中的所有线程

 

六、Thread类中的常见构造方法

Thread(String name):

给线程起一个名字,这个名字对于程序的执行没影响,但是对于调试来说还是挺有用的~

如果不手动设置,也会有默认的名字,形如 Thread-0、Thread-1、...... 


七、Thread的常见属性

这里的后台线程也叫守护线程

  • 前台线程会阻止进程的结束,前台线程的工作没做完,进程是完不了的,
  • 后台线程不会阻止进程的结束,后台线程的工作没做完,进程照样可以结束,
  • 换句话说,进程会保证所有的前台线程都执行完了 才会退出~

我们手写的线程默认都是前台线程,包括main也是默认前台,但是我们可以通过setDeamon()设置成后台线程

public class Demo7 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },("我的线程"));
        t.start();
    }
} 

 

分析:

因为该线程是一个前台线程,需要等待其运行结束,进程才会结束,所以会一直执行下去~

再如:我们可以把他手动设置成后台线程:

 isAlive判断当前线程是否还存活,调用start前isAlive是false,调用后isAlive是true

虽然线程把run里要干的事干完后就销毁了,pcb也随之释放了,但是Thread t这个对象还不一定被释放,此时isAlive也是false,t的销毁要等GC回收

总结:

八、中断线程

所谓的 "中断线程",就是让线程尽快把入口方法执行结束~

方法一:直接自己定义 标志位 

package J_1125;
public class Main {
    //用一个布尔变量来表示 线程是否要结束
    //这个变量是一个成员变量,而不是局部变量
    private static boolean isQuit =  false;
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (!isQuit) {
                System.out.println("线程运行中......");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("新线程执行结束!");
        });
        t.start();

        Thread.sleep(5000);
        System.out.println("控制新线程退出!");
        isQuit = true;
    }
}

运行结果:

这个代码中,控制线程结束,主要是这个线程里有一个循环,这个循环执行完,就算结束了~

方法二:使用 Thread类 中自带的标志位~ 

Thread 其实内置了一个标志位,不需要咱们去手动创建标志位

Thread.currentThread().isInterrupted()
 
--currentThread() 是 Thread类的静态方法,获取到当前线程的实例,这个方法中有一个线程会调用它
--线程1 调用这个方法,就能返回线程1 的 Thread对象;
--线程2 调用这个方法,就能返回线程2 的 Thread对象~
--类似于 JavaSE 里面的 this~
 
--isInterrupted() 为判定内置的标志,可以获取到标志位的值,为 true 表示线程要被中断~
package thread;
 
public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() ->{
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("线程运行中......");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
 
        Thread.sleep(5000);
        System.out.println("控制新线程退出!");
        t.interrupt();
    }
}

 

 

 说明:

        调用了 interrupt,产生了一个异常,异常虽然出现了,但是线程仍然在继续运行

注意理解 interrupt方法的行为:

        如果 t 线程没有处在阻塞状态,此时 interrupt 就会修改内置的标志位
        如果 t 线程正在处于阻塞状态,此时 interrupt 就让线程内部产生阻塞的方法

例如:

  1. 线程在sleep中休眠,此时调用interrupt会把t线程唤醒,从sleep中提前返回。
  2. interrupt会触发sleep内部的异常,导致sleep提前返回 


上述循环代码中,正好异常被捕获了,而捕获之后,啥也没有干只是打印了一个调用栈

interrupt会做两件事:

  1. 把线程内部的标志位(boolean)设置成true,表示终止
  2. 如果线程在进行sleep,就会触发异常,把sleep唤醒,sleep又把刚才设置的标志位设置回false(继续),这就表示sleep异常被catch完了之后循环还要继续执行

注意:调用interrupt只是通知终止,线程会不会终止,还得看代码怎么写的

九、等待线程 - join() 

线程是一个随机调度的过程

等待线程就是一种确定线程执行顺序的辅助手段,来控制两个线程的结束顺序。

join() 的行为:

  1. 如果被等待的线程 还没执行完,就阻塞等待~
  2. 如果被等待的线程 已经执行完了,就直接返回~

 

main 有点特殊,不太方便 join()~

一般情况下,想让谁阻塞,谁就调用 join() 即可 ~

如:要实现让 t2 等待 t1,main 等待 t2,就可以让main去调用 t2.join(),t2 再调用 t1.join() 图像 小部件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/37084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库的常用操作

数据库的分类 数据库大体可以分为 关系型数据库 和 非关系型数据库 关系型数据库:是指采用了关系模型来组织数据的数据库,关系模型指的就是二维表格模型,关系型数据库都基于标准的SQL,只是内部一些实现有区别 常见关系型数据库…

奇舞周刊第 473 期: Rollup 与 Webpack 的 Tree-shaking

记得点击文章末尾的“ 阅读原文 ”查看哟~下面先一起看下本期周刊 摘要 吧~奇舞推荐■ ■ ■Rollup 与 Webpack 的 Tree-shakingRollup 和 Webpack 是目前项目中使用较为广泛的两种打包工具,去年发布的 Vite 中打包所依赖的也是 Rollup;在对界面加载效率…

Java项目:JSP手机商城管理系统包含前台

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目分为前后台,分为管理员与普通用户两种角色,管理员登录后台,普通用户登录前台; 管理员角色…

编译原理之词法分析器随笔和简单实现

借鉴: 编译原理之美. 极客时间上 什么是词法分析 编译原理:词法分析简单的来说就是在字符串中提取一系列的word单词. 编译器的眼里, 我们的一切输入都是什么? 都是一个一个的字符串. 所以编译器干的就是字符串解析工作. 词法分析:自然就是解析出来…

Vue中el和data的写法与 MVVM模型

目录 el和data的两种写法 el的两种写法 data的两种写法 data与el的写法小结 MVVM模型 MVVM模型小结 el和data的两种写法 el的两种写法 <body> <div id"root"> hello,{{name}}</div><script type"text/javascript">const vm ne…

iwebsec靶场 SQL注入漏洞通关笔记3- bool注入(布尔型盲注)

系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1- 数字型注入_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2- 字符型注入&#xff08;宽字节注入&#xff09;_mooyuan的博客-CSDN博客 目录 文章目录 前言 一、源码分析 二、sqlmap渗透 1.注入命令 2.完整交互过程…

小技巧1:如何给pip install进行换源

大家好&#xff0c;我是Kamen Black君&#xff0c;今天给大家介绍一个小技巧&#xff1a;如何给pip安装进行换源。 print("祝大家每天快乐&#xff0c;love and peace&#xff01;") 曾几何时&#xff0c;当我准备好了一段很有趣的代码准备进行运行时&#xff0c;发…

亚马逊云科技re:Invent:这些成功的数据驱动新企业背后的秘诀是什么?

北京时间11月29号&#xff0c;亚马逊云科技年度峰会re:Invent 2022将在拉斯维加斯开幕。这场年度最重磅的云计算技术大会不仅是科技盛宴&#xff0c;也是亚马逊云科技与诸多客户交流互鉴的绝佳平台&#xff0c;今天带大家认识一下几位资深云计算用户&#xff0c;以及他们和re:I…

ENVI5.6超详细教程大全-从安装包到安装流程详解

一、获取资源&#xff1a; https://www.xsoftnet.com/share/a000HzsWPCJXi.html二、安装教程&#xff1a;安装前请关闭杀毒软件&#xff0c;系统防火墙&#xff0c;断开网络连接 1.解压ENVI5.6安装包&#xff1a;ENVI5.6.zip 2.找到envi56-win.exe文件&#xff0c;双击进行安装…

Centos7 安装部署Kubernetes(k8s)集群实现过程

一.系统环境 服务器版本docker软件版本CPU架构CentOS Linux release 7.4.1708 (Core)Docker version 20.10.12x86_64二.前言 下图描述了软件部署方式的变迁&#xff1a;传统部署时代&#xff0c;虚拟化部署时代&#xff0c;容器部署时代。 传统部署时代&#xff1a; 早期&am…

制作一个简单HTML游戏网页(HTML+CSS)仿龙之谷网络游戏官网

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

vite+ts-3-后端准备(慢慢更新)

random recording 随心记录 What seems to us as bitter trials are often blessings in disguise. 看起来对我们痛苦的试炼&#xff0c;常常是伪装起来的好运。 应用tskoamysql构建高可维护性和扩展性架构 数据库基础 定义和特点 数据库就是按照特定格式存储数据的文件集合&…

二本Java渣渣9面字节遭虐,苦修数月深造这份宝典,终进阿里

见过真正头铁的程序员吗&#xff1f;如题所示&#xff0c;真人真事&#xff0c;这位二本的兄弟在这短短几个月内海投了638份简历&#xff0c;全挑的大厂岗位投的&#xff0c;仅字节跳动就前前后后面试了九次&#xff0c;他说&#xff1a;没有撤退可言。 九次面试经历也是奇了—…

西门子精彩触摸屏SMART V3组态用户管理的具体方法和步骤

西门子精彩触摸屏SMART V3组态用户管理的具体方法和步骤 如下图所示,新建一个项目,在连接中添加连接,触摸屏的IP地址要和 PLC的IP地址保持在同一网段, 如下图所示,在变量中添加一个变量, 如下图所示,在画面1中添加一个IO域,并连接上图中的变量, 如下图所示,设置…

python数据分析绘图

ROC-AUC曲线&#xff08;分类模型&#xff09; 混淆矩阵 混淆矩阵中所包含的信息 True negative(TN)&#xff0c;称为真阴率&#xff0c;表明实际是负样本预测成负样本的样本数&#xff08;预测是负样本&#xff0c;预测对了&#xff09;False positive(FP)&#xff0c;称为假…

HTML5期末大作业:游戏网站设计与实现——基于bootstrap响应式游戏资讯网站制作HTML+CSS+JavaScript

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

力扣每日一题:882. 细分图中的可到达节点【最短路径dijkstra】

给你一个无向图&#xff08;原始图&#xff09;&#xff0c;图中有 n 个节点&#xff0c;编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链&#xff0c;每条边之间的新节点数各不相同。 图用由边组成的二维数组 edges 表示&#xff0c;其中 edges[i] [ui, vi, cn…

搭建集群常用脚本

rsync同步工具&#xff0c;编写xsync脚本 yum install -y rsynchostname处理&#xff1a; vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomai…

花房集团通过上市聆讯:5个月营收20亿 周鸿祎是大股东

雷递网 雷建平 11月25日花椒母公司花房集团今日正式通过聆讯&#xff0c;准备在港交所上市。这之前&#xff0c;360集团孵化的360数科、鲁大师也分别在美股和港股上市。360数科还将于下周在香港上市。这意味着&#xff0c;360董事长周鸿祎将在香港收获两个IPO。5个月营收20亿 经…

音视频开发之音频基础知识!

前言&#xff1a; 在音视频开发中&#xff0c;音频也是一个重要功能之一。在音频开发中有两个重要的概念&#xff0c;一个是PCM数据格式&#xff0c;另外一个是AAC数据格式。下面我们会重点介绍&#xff01;一、PCM重要音频参数&#xff1a; PCM数据也被称之为脉冲编码调制数据…