【JavaEE】多线程(1)

在这里插入图片描述
🎆🎆🎆个人主页🎆🎆🎆
🎆🎆🎆JavaEE专栏🎆🎆🎆
🎆🎆🎆计算机是怎么工作的🎆🎆🎆’

文章目录

  • 1.进程
    • 1.1进程的概念
    • 1.2为什么需要多进程
    • 1.3多进程的坏处
    • 2.线程
    • 2.1引入线程的原因
    • 2.2线程的属性
    • 2.3线程的代码写法
    • 2.4Thread构造方法
    • 2.5Thread的等待
    • 2.6Thread的状态

1.进程

1.1进程的概念

进程是计算机中程序执行的一个实例,是操作系统进行资源分配和调度的基本单位。每个进程都拥有独立的虚拟地址空间、执行状态、寄存器集合等,是操作系统执行多任务的基础.

1.2为什么需要多进程

在现在这个时代,动不动就是8核16线程的CPU甚至更大的CPU,不像以前一个CPU只有一个核心,但是任务又多,核心数又少,导致效率很低,但现在核心数变多了,那么任务就可以同时在多个核心下一起运行就引出了多进程的概念.

1.3多进程的坏处

每创建一次进程就需要系统分配资源(内存资源和文件资源),进程结束之后需要系统去释放资源,如果出现频繁的创建进程和结束进程,这样资源消耗巨大会导致系统响应变慢.所以我们需要引进"线程".

2.线程

2.1引入线程的原因

线程(Thread)是一个轻量级进程,与"进程"相比在创建和销毁上的开销更小,主要原因是:一个进程被创建 系统会给进程分配资源,而一个进程可以有多个线程,这些线程不需要独自一个一个被系统分配资源,它们可以共享系统为进程分配的资源,在销毁的时候也只需要销毁进程的资源即可,这样下来减少了创建与销毁的开销,线程不仅共享进程的资源,而且每一个线程都有自己的属性.

2.2线程的属性

1)ID(此处的id与系统中pcb中的id是不一样的,jvm自己单独搞了一套自己的id体系,但是本质上与pcb中的id是一一对应的)
获取方法:getId()
2)名称
获取方法:getName()
3)状态
获取方法:getState()
4)优先级
获取方法:getPriority()
虽然java提供了优先级的接口,但实际上你去修改了优先级,现象也不是很明显,这里的修改只是作为一个参考,具体还是看系统本身
5)是否后台线程
获取方法:isDaemon()
前台线程:前台线程结束了,那么这个线程就结束了,如果有多个前台线程那么等到最后一个前台线程结束了,那么这个线程就结束了
后台线程:后台线程结束了,不会影响整个线程的进度,但前台线程结束了,整个线程就结束了,那么自然后台线程也就结束了
main线程就是前台线程
还有就是像我们自己创建的线程默认情况下也是前台线程,可以通过setDaemon()方法来把线程设置后台线程
后台线程比如有gc(垃圾回收——对内存还有文件资源的回收) 是一个周期性持续执行的线程,不会自己主动结束
这是将前台线程设置为后台线程代码:

public class Deom7 {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("打印thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.setDaemon(true);
        t1.start();
    }

}

注意:
nterrupt和isInterruptted方法
Thread.currentThread()这个是一个static方法,这个方法可以获取到当前线程也就是t这个引用
isInterruptted()方法就是线程内置标志位
true 表示线程要终止
false 表达线程要继续执行
调用这个interrupt()方法:
可以将标志位修改位true还可以唤醒sleep等阻塞
但是调用这个方法之后,如果程序中有sleep方法那么不仅仅会唤醒sleep而且还会清除修改的标志位,此处的清除标志位的目的就是将控制权交给程序猿
如果没有sleep,那么就是一个简简单单的修改标志位
6)是否存活
获取方法:isAlive()
jvm提供的Thread类中的线程与系统中的PCB的生命周期是不一样的
当我已经实例化Thread对象的时候,此时的系统还没有创建PCB
当我们执行到了start()方法的时候,系统才创建PCB
7)是否被中断
获取方法:isInterrupted()

2.3线程的代码写法

总共有五种常见的写法:
1.创建Thread子类
创建一个子类继承于Thread类重写父类的run方法

class MyThread extends Thread {
    @Override
    public void run() {
        while(true) {
            System.out.println("打印Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Deom1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new MyThread();
        t1.start();
       while(true) {
            System.out.println("打印main");
            Thread.sleep(1000);
        }
    }

2.通过实现Runnable接口
实现接口,重写接口中的run方法,这种方法可以解耦合

class MyRunnable implements Runnable{

    @Override
    public void run() {
        while(true) {
            System.out.println("打印Thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Deom2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyRunnable());
        t1.start();
        while(true) {
            System.out.println("打印main");
            Thread.sleep(1000);
        }
    }

}

3.创建匿名内部类继承Thread类

public class Deom3 {
    public static void main(String[] args) throws InterruptedException {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("打印Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }.start();


        while (true) {
            System.out.println("打印main");
            Thread.sleep(1000);
        }
    }
}

4.创建匿名内部类实现Runnable接口

public class Deom4 {
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("打印Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();


        while (true) {
            System.out.println("打印main");
            Thread.sleep(1000);
        }

    }


}

5.使用lambda表达式

public class Deom5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                System.out.println("打印thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();

        while(true) {
            System.out.println("打印main");
            Thread.sleep(1000);
        }
    }
}

3,4,5这三种方式好处就是代码简洁,坏处就是可读性不高.
此处提到的run方法与start方法;
run方法:作用就是描述一个任务,然后线程实现之后去实现的任务就是这个run方法中描述的任务
start方法:作用就是创建线程和执行线程

2.4Thread构造方法

1)Thread()无参数
2)Thread(Runnable target) 使用Runnable对象创建对象
3)Thread(String name) 创建线程对象,并命名
4) Thread(Runnable target,String name)使用Runnable对象创建线程对象,并命名

2.5Thread的等待

由于线程的调度是抢占式的,所以在线程的执行顺序有不确定性,我们就需要引用一个join方法来解决。
在哪个线程中调用join方法就哪个线程阻塞等待
比如:在main线程中调用了t1.join,那么就是main线程等待阻塞,等t1线程结束之后,main线程才执行。
join不参数的属于死等,无限制的去等,这样有时候在有些场景不适用,所以还有一个有时间版本的join方法
join(long millis)
例子:
t1.join(10)被main线程调用,如果t1线程让main线程等待超过了10ms,那么main线程就不会继续等待阻塞下去,就会继续执行main线程下面的代码

使用slee控制的式"线程休眠时间 “而不是"两个代码执行的间隔时间”

main线程等t1线程:

public class Deom8 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t1.start();
        t1.join();
        System.out.println("main线程结束");
    }
}

让t2等t1线程,main线程等t1和t2线程:

public class Deom9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
            System.out.println("t1线程结束");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread t2= new Thread(() -> {
            try {
                t1.join();
            System.out.println("t2线程结束");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });


        t1.start();
        t2.start();
        t2.join();
        System.out.println("main线程结束");
    }

}

main线程只等待t1线程3秒,但t1线程需要5秒执行时间,但时间一到main线程也不会等待t1:

public class Deom10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("t1线程结束");
        });

        t1.start();
        t1.join(3000);
        System.out.println("main线程结束");
    }
}

2.6Thread的状态

1.NEW Thread对象有了,但还未调用start系统内部的线程还未创建
2.TERMINATED 线程已经终止了,系统内核中的线程已经销毁,但对象还在
3.RUNNABLE 就绪状态 指这个线程要么已经在CPU中执行,要么随时都可以被CPU调度
4.WAITING 死等进入阻塞
5.TIMED_WAITING 带有时间的等
6.BLOCKED 进行锁竞争的时候产生的阻塞

绘图描述(简化):
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第七在线惊艳亮相第11届奥莱峰会,AI驱动零售供应链升级

2024年5月22-24日&#xff0c;第11届奥莱领秀峰会暨2024奥莱产业经济论坛在南京盛大举行。论坛上&#xff0c;智能商品计划管理系统服务商第七在线凭借富有前瞻性的AI技术&#xff0c;引领零售供应链迈入全新升级阶段&#xff0c;赢得了与会嘉宾的广泛关注与赞誉。 峰会由中国奥…

【一百】【算法分析与设计】N皇后问题常规解法+位运算解法

N皇后问题 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 给出一个nnn\times nnn的国际象棋棋盘&#xff0c;你需要在棋盘中摆放nnn个皇后&#xff0c;使得任意两个皇后之间不能互相攻击。具体来说&#xff0c;不能存在两个皇后位于同…

BUUCTF Crypto RSA详解《1~32》刷题记录

文章目录 一、Crypto1、 一眼就解密2、MD53、Url编码4、看我回旋踢5、摩丝6、password7、变异凯撒8、Quoted-printable9、篱笆墙的影子10、Rabbit11、RSA12、丢失的MD513、Alice与Bob14、大帝的密码武器15、rsarsa16、Windows系统密码17、信息化时代的步伐18、凯撒&#xff1f;…

springboot基本使用十一(自定义全局异常处理器)

例如&#xff1a;我们都知道在java中被除数不能为0&#xff0c;为0就会报by zero错误 RestController public class TestController {GetMapping("/ex")public Integer ex(){int a 10 / 0;return a;}} 打印结果&#xff1a; 如何将这个异常进行处理&#xff1f; 创…

java——网络原理初识

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 目录 1.网络通信概念初识1.1 IP地址1.2端口号1.3协议1.3.1协议分层协议分层带来的好处主要有两个方面 1.3.2 TCP/IP五层 (或四层模型)1.3.3 协议的层和层之间是怎么配合工作的 1.网络通信概念初识…

RLC防孤岛保护装置如何工作的?

什么是RLC防孤岛保护装置&#xff1f; 孤岛保护装置是电力系统中一道强大的守护利器&#xff0c;它以敏锐的感知和迅速的反应&#xff0c;守护着电网的平稳运行。当电网遭遇故障或意外脱离主网时&#xff0c;孤岛保护装置如同一位机警的守门人&#xff0c;立刻做出决断&#xf…

算法(七)插入排序

文章目录 插入排序简介代码实现 插入排序简介 插入排序&#xff08;insertion sort)是从第一个元素开始&#xff0c;该元素就认为已经被排序过了。然后取出下一个元素&#xff0c;从该元素的前一个索引下标开始往前扫描&#xff0c;比该值大的元素往后移动。直到遇到比它小的元…

MySQL 索引的使用

本篇主要介绍MySQL中索引使用的相关内容。 目录 一、最左前缀法则 二、索引失效的场景 索引列运算 字符串无引号 模糊查询 or连接条件 数据分布 一、最左前缀法则 当我们在使用多个字段构成的索引时&#xff08;联合索引&#xff09;&#xff0c;需要考虑最左前缀法则…

【VTKExamples::Utilities】第十七期 ZBuffer

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例ZBuffer,并解析接口vtkWindowToImageFilter,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ…

【面试八股总结】MySQL事务:事务特性、事务并行、事务的隔离级别

参考资料&#xff1a;小林coding 一、事务的特性ACID 原子性&#xff08;Atomicity&#xff09; 一个事务是一个不可分割的工作单位&#xff0c;事务中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部不完成&#xff0c;不会结束在中间某个环节。原子性是通过 undo …

Arm发布Cortex X925、A725、A520,Armv9.2架构

随着半导体行业的不断发展&#xff0c;Arm 通过突破技术界限&#xff0c;为终端用户提供尖端解决方案&#xff0c;在核心和 IP 架构创新方面处于领先地位&#xff0c;尤其是在移动领域。2024 年&#xff0c;Arm 的年度战略进步重点是增强去年的 Armv9.2 架构&#xff0c;并带来…

Windows系统安装openvino(2024.1.0)

一、openvino下载&#xff1a; 下载地址&#xff1a;下载英特尔发行版 OpenVINO 工具套件 (intel.cn) 下载完之后将压缩包解压&#xff0c;然后重命名文件夹为openvino_2024.1.0。 二、环境配置 以python环境为例&#xff1a;&#xff08;建议使用moniconda虚拟环境来安装&am…

鸿蒙ArkTS声明式开发:跨平台支持列表【背景设置】 通用属性

背景设置 设置组件的背景样式。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版…

【免费Web系列】JavaWeb实战项目案例五

这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 新增员工 前面我们已经实现了员工信息的条件分页查询。 那今天我们要实现的是新增员工的功能实现&#xff0c;页面原型如下&#xff1a; ​ 首先我们先完成"新增员工"的功能开发&#xff0…

ODBC访问达梦数据库Ubuntu18.04 x86-x64(亲测有效)

ODBC访问达梦数据库Ubuntu18.04 x86-x64 第1步&#xff1a;安装unixodbc驱动,使用下面命令。第2步&#xff1a;拷贝已经安装好的达梦数据库驱动程序第3步&#xff1a;配置ODBC必要的参数文件&#xff0c;如下图第4步&#xff1a;设置环境变量第5步&#xff1a;连接测试 说明&am…

Github单个文件或者单个文件夹下载插件

有时候我们在github上备份了一些资料&#xff0c;比如pdf,ppt&#xff0c;md之类的,需要用到的时候只要某个文件即可&#xff0c;又不要把整个仓库的zip包下载下来&#xff0c;毕竟有时文件太多&#xff0c;下载慢&#xff0c;我们也不需要所有资料&#xff0c;那么就可以使用到…

docker安装Mysql5.7版本

首先Linux系统已经安装好了docker应用。 1.搜索镜像 docker search mysql 2.拉取5.7的镜像 总之,选starts最多的那个就对了。 docker pull mysql:5.7 ~ docker pull mysql:5.7 5.7: Pulling from library/mysql fc7181108d40: Downloading [============> …

C语言数据结构(超详细讲解)| 二叉树的实现

二叉树 引言 在计算机科学中&#xff0c;数据结构是算法设计的基石&#xff0c;而二叉树&#xff08;Binary Tree&#xff09;作为一种基础且广泛应用的数据结构&#xff0c;具有重要的地位。无论是在数据库索引、内存管理&#xff0c;还是在编译器实现中&#xff0c;二叉树都…

Github 如何配置 PNPM 的 CI 环境

最近出于兴趣在写一个前端框架 echox&#xff0c;然后在 Github 上给它配置了最简单的 CI 环境&#xff0c;这里简单记录一下。 特殊目录 首先需要在项目根目录里面创建 Github 仓库中的一个特殊目录&#xff1a;.github/workflows&#xff0c;用于存放 Github Actions 的工作…

MyBatis基础理解教程,详细分步基础查询表数据练习(通俗易懂、实时更新)

一、MyBatis是什么 MyBatis 是一个持久层框架&#xff0c;简化JDBC开发&#xff0c;它提供了一个从 Java 应用程序到 SQL 数据库的桥梁&#xff0c;用于数据的存储、检索和映射。MyBatis 支持基本的 SQL 操作、高级映射特性以及与 Maven 等构建工具的集成。 二、持久层是什么…