【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 {@Overridepublic 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{@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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 进行锁竞争的时候产生的阻塞
绘图描述(简化):

相关文章:
【JavaEE】多线程(1)
🎆🎆🎆个人主页🎆🎆🎆 🎆🎆🎆JavaEE专栏🎆🎆🎆 🎆🎆🎆计算机是怎么工作的🎆dz…...
相对位姿估计
相对位姿估计 示意图 理论推导 离线数据库: P的位置 P [ X , Y , Z ] T P[X,Y,Z]^{T} P[X,Y,Z]T 相机内参 k 1 k_{1} k1 安卓手机: 相机内参 k 2 k_{2} k2 两个像素点位置 : p 1 和 p 2 p_1和p_2 p1和p2 公式一:…...
记一次 .NET某工业设计软件 崩溃分析
一:背景 1. 讲故事 前些天有位朋友找到我,说他的软件在客户那边不知道什么原因崩掉了,从windows事件日志看崩溃在 clr 里,让我能否帮忙定位下,dump 也抓到了,既然dump有了,接下来就上 windbg …...
2020 6.s081——Lab5:Lazy page allocation
再来是千年的千年 不变是眷恋的眷恋 飞越宇宙无极限 我们永不说再见 ——超兽武装 完整代码见:SnowLegend-star/6.s081 at lazy (github.com) Eliminate allocation from sbrk() (easy) 顾名思义,就是去掉sbrk()中调用growproc()的部分。1s完事儿。 Laz…...
华为认证学习笔记:生成树
以太网交换网络中为了进行链路备份,提高网络可靠性,通常会使用冗余链路。但是使用冗余链路会在交换网络上产生环路,引发广播风暴以及MAC地址表不稳定等故障现象,从而导致用户通信质量较差,甚至通信中断。为解决交换网络…...
leetcode 97.交错字符串
思路:LCS 其实也是同一个类型的题目,一般涉及到这种子序列的字符串问题的时候,状态的设置基本上都应该是以...结尾为状态的。这里同样,设置用dp[i][j]为s1,s2字符以i,j结尾能否拼接成s3[ij]。 那么,首先就…...
The Missing Semester ( Shell 工具和脚本 和 Vim)
管道符号 (1)管道符号 | 将前一个命令的输出作为下一个命令的输入 例如: 以下为 ./semester输出中提取包含 "Last-Modified" 的行并写入文件 last-modified.txt./semester | grep "Last-Modified" > ~/last-modif…...
【Uniapp微信小程序】自定义水印相机、微信小程序地点打卡相机
效果图 template 下方的image图片自行寻找替换! <template><view><camerav-if"!tempImagePath && cameraHeight ! 0":resolution"high":frame-size"large":device-position"device":flash"f…...
SimPO: Simple Preference Optimization with a Reference-Free Reward
https://github.com/princeton-nlp/SimPO 简单代码 class simpo(paddle.nn.Layer):def __init__(self):super(OrPoLoss, self).__init__()self.loss paddle.nn.CrossEntropyLoss()def forward(self,neg_logit, neg_lab, pos_logit, pos_lab,beta,gamma):neg_logit paddle.n…...
CDH6.3.2安装文档
前置环境: 操作系统: CentOS Linux release 7.7 java JDK : 1.8.0_231 1、准备工作 准备以下安装包: Cloudera Manager: cloudera-manager-agent-6.3.1-1466458.el7.x86_64.rpm cloudera-manager-daemons-6.3.1-1466458.el…...
Java实战入门:深入解析Java中的 `Arrays.sort()` 方法
文章目录 一、方法定义参数说明返回值 二、使用场景三、实现原理四、示例代码示例一:对整型数组排序示例二:对字符串数组排序示例三:对自定义对象数组排序 五、注意事项六、总结 在Java编程中,Arrays.sort() 方法是一个非常常用的…...
JavaScript的垃圾回收机制
No.内容链接1Openlayers 【入门教程】 - 【源代码示例300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3Cesium 【入门教程】 - 【源代码图文示例200】 4MapboxGL【入门教程】 - 【源代码图文示例150】 5前端就业宝典 【面试题详细答案 1000】 文章目录 一、垃圾…...
小程序使用Canvas设置文字竖向排列
在需要使用的js页面引入js文件,传入对应参数即可 /** * 文本竖向排列 */ function drawTextVertical(context, text, x, y) {var arrText text.split();var arrWidth arrText.map(function (letter) {return 26; // 字体间距,需要自定义可以自己加参数,根据传入参数进行…...
GPT-4o:重塑人机交互的未来
一个愿意伫立在巨人肩膀上的农民...... 一、推出 在人工智能(AI)领域,自然语言处理(NLP)技术一直被视为连接人类与机器的桥梁。近年来,随着深度学习技术的快速发展,NLP领域迎来了前所未有的变革…...
大语言模型拆解——Tokenizer
1. 认识Tokenizer 1.1 为什么要有tokenizer? 计算机是无法理解人类语言的,它只会进行0和1的二进制计算。但是呢,大语言模型就是通过二进制计算,让你感觉计算机理解了人类语言。 举个例子:单1,双2&#x…...
Linux自动挂载服务autofs讲解
1.产生原因 2.配置文件讲解 总结:配置客户端,先构思好要挂载的目录如:/abc/cb 然后在autofs.master中编辑: /abc(要挂载的主目录) /etc/qwe(在这个文件里去找要挂载的副目录,这个名…...
堆结构知识点复习——玩转堆结构
前言:堆算是一种相对简单的数据结构, 本篇文章将详细的讲解堆中的知识点, 包括那些我们第一次学习堆的时候容易忽略的内容, 本篇文章会作为重点详细提到。 本篇内容适合已经学完C语言数组和函数部分的友友们观看。 目录 什么是堆 建堆算法…...
JS数据类型运算符标准库
目录 数据类型运算符标准库对象Object对象属性描述对象Array对象包装对象Boolean对象Number对象String对象Math对象Date对象...
单片机之从C语言基础到专家编程 - 4 C语言基础 - 4.13数组
C语言中,有一类数据结构,它可以存储一组相同类型的元素,并且可以通过索引访问这些元素,没错,这类数据结构就是数组。数组可以说是C语言中非常重要的数据结构之一了。使用数组可以是程序逻辑更加清晰,也更加…...
【码银送书第二十期】《游戏运营与出海实战:策略、方法与技巧》
市面上的游戏品种繁杂,琳琅满目,它们是如何在历史的长河中逐步演变成今天的模式的呢?接下来,我们先回顾游戏的发展史,然后按照时间轴来叙述游戏运营的兴起。 作者:艾小米 本文经机械工业出版社授权转载&a…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...
