东莞网站建设纸品包装/网站建设公司大型
哈喽~大家好呀,这篇来看看JAVA进程和线程。
🥇个人主页:个人主页
🥈 系列专栏:【日常学习上的分享】
🥉与这篇相关的文章:
Redis快速入门及在Java中使用Redis Redis快速入门及在Java中使用Redis_程序猿追的博客-CSDN博客 为什么不推荐使用Lombok?@Data不香吗? 为什么不推荐使用Lombok?@Data不香吗?-CSDN博客 Mybatis报错: Parameter ‘XXX‘ not found. Available parameters are [arg1, arg0, param1, param2]解决方案及问题原因 Mybatis报错: Parameter ‘XXX‘ not found. Available parameters are [arg1, arg0, param1, param2]解决方案及问题原因-CSDN博客
目录
一、前言
1、进程和线程概念
2、线程的优先级
二、Thread 类
三、Runnable 接口
四、线程同步
1、synchronized
2、使用方式
五、死锁问题
六、生产者与消费者实战案例
七、图书推荐
一、前言
1、进程和线程概念
什么是进程
进程就是正在运行的程序,它是系统资源调度的独立单位,并且一个进程可以执行多个任务,而线程就是程序执行的任务,它是程序使用CPU的基本单位,因此也可以说线程是依赖于进程的。像比如任务管理器里面的运行任务就是线程。
单进程与多进程的概述
单进程的计算机一次只能做一件事情,而多进程的计算机可以做到一次做不同的事情,比如一边听音乐,一边听打游戏,这两件事情虽然感觉起来是在同时一起进行的,但其实是CPU在做着程序间的高效切换,这才让我们觉得是同时进行的。
什么是线程
线程
是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元
,是处理器
调度和分派的基本单位
。
一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。
线程的状态
线程的生命周期
- 新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
- 就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
- 运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
- 阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
-
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
-
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
-
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
-
- 死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
2、线程的优先级
每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
二、Thread 类
使用 Thread 来创建线程,类继承与 Thread 类。继承类必须重写 run() 方法,该方法是新线程的入口点。它也必须调用 start() 方法才能执行。
格式
package com.zte.thread;public class ThreadA extends Thread{// run() 方法线程执行的第一步,同main方法@Overridepublic void run() {}}
示例
public class ThreadA extends Thread{// run() 方法线程执行的第一步,同main方法@Overridepublic void run() {for (int i = 1; i <= 200; i++) {System.out.println("i : " + i);}}}public class ThreadB extends Thread{@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println("j :" + i);}}
}public class Text {public static void main(String[] args){ThreadA a = new ThreadA();ThreadB b = new ThreadB();a.start();b.start();}
}
运行结果
打印太多了,我们只看关键的一部分,很明显多个线程明显在抢占资源
扩:
这里我们看下 start() 与 run() 的区别
start() :
它的作用是启动一个新线程。
通过start()方法来启动的新线程,处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。start()不能被重复调用。用start方法来启动线程,真正实现了多线程运行,即无需等待某个线程的run方法体代码执行完毕就直接继续执行下面的代码。这里无需等待run方法执行完毕,即可继续执行下面的代码,即进行了线程切换。
run() :
run()就和普通的成员方法一样,可以被重复调用。
如果直接调用run方法,并不会启动新线程!程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到多线程的目的。
总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里
简单来说就是 start() 可以创建多个线程,不能重复调用,而 run() 创建单个线程,能重复调用。
三、Runnable 接口
创建一个线程,最简单的方法是创建一个实现 Runnable 接口的类,使用 run 来调用线程
示例
public class ThreadA implements Runnable{// run() 方法线程执行的第一步,同main方法@Overridepublic void run() {for (int i = 1; i <= 200; i++) {try {Thread.sleep(1000); // 让线程睡眠一会} catch (InterruptedException e) {e.printStackTrace();}System.out.println("i : " + i);}}}public class ThreadB implements Runnable{@Overridepublic void run() {for (int i = 0; i < 200; i++) {try {Thread.sleep(1000); // 让线程睡眠一会} catch (InterruptedException e) {e.printStackTrace();}System.out.println("j :" + i);}}
}public class Text {public static void main(String[] args){ThreadA a = new ThreadA();ThreadB b = new ThreadB();a.run();b.run();}
}
扩:
1、当我们使用了 Runnable 实例化对象就不能调用 start 方法了,只能用 run 了。
2、sleep 的意思是强制当前正在执行的线程休眠(暂停执行),例如:【Thread.sleep(long millis)】当线程睡眠时它不会在苏醒之前返回到可运行状态;当睡眠时间到期后才会返回到可运行状态。里面放的毫秒值。
四、线程同步
1、synchronized
什么是 synchronized ?
答:synchornized 是 Java 中的一个关键字,解决的是多个线程之间访问资源的同步性,synchronized 关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
在上面我们遇到了线程抢占的问题,而 synchronized 就是来解决这问题的。
应用场景
2、使用方式
修饰实例方法:作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁
synchronized void method() {//业务代码
}
修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。
synchronized static void method() {//业务代码
}
修饰代码块 :指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁。synchronized(类.class) 表示进入同步代码前要获得 当前 class 的锁
synchronized(this) {//业务代码
}
案例(银行存钱与取钱)
分析:银行比作容器,取钱与存放是两个进程,并且不能同时进行。
public class Account extends Thread{private int balance = 1000;Object o = new Object(); // 或者用 thispublic void withdraw(int n){synchronized (o){balance -= n;System.out.println("取了 : " + n + " 还剩 : " + balance);}}public void deptdraw(int n){synchronized (o){balance += n;System.out.println("存了 : " + n + " 还剩 : " + balance);}}}public class PersonA extends Thread{private Account account;public Account getAccount() {return account;}public void setAccount(Account account) {this.account = account;}@Overridepublic void run() {for (int i = 0; i < 3; i++) {account.withdraw(100);}}}public class PersonB extends Thread{private Account account;public Account getAccount() {return account;}public void setAccount(Account account) {this.account = account;}@Overridepublic void run() {for (int i = 0; i < 3; i++) {account.deptdraw(100);}}}public class Text {public static void main(String[] args){Account acc = new Account();PersonA a = new PersonA();PersonB b = new PersonB();a.setAccount(acc);b.setAccount(acc);b.start();a.start();}
}
运行结果
五、死锁问题
什么是死锁?
答:线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。
简单来讲就是,t1 线程在等 t2 线程,t2 线程也在等 t1 线程,这就陷入到了死循环了,这就叫死锁。
示例
public class AddAndSub {public Object objectA = new Object();public Object objectB = new Object();public void add(){synchronized (objectA){System.out.println(Thread.currentThread().getName() + "我获取到了a");try {objectA.wait();System.out.println("我等到了");} catch (InterruptedException e) {e.printStackTrace();}synchronized (objectB){System.out.println(Thread.currentThread().getName() + "我获取到了b");}System.out.println(Thread.currentThread().getName() + "我失去了b");}System.out.println(Thread.currentThread().getName() + "我失去了a");}public void sub(){synchronized (objectB){System.out.println(Thread.currentThread().getName() + "我获取到了b");try {Thread.sleep(1000);
// System.out.println("我等到了");} catch (InterruptedException e) {e.printStackTrace();}// synchronized (objectB){System.out.println(Thread.currentThread().getName() + "我获取到了a");
// objectA.notify();
// }System.out.println(Thread.currentThread().getName() + "我失去了a");}System.out.println(Thread.currentThread().getName() + "我失去了b");}}public class TB extends Thread{public AddAndSub addAndSub;@Overridepublic void run() {addAndSub.sub();}
}public class TA extends Thread{public AddAndSub addAndSub;@Overridepublic void run() {addAndSub.add();}
}public class Text {public static void main(String[] args){AddAndSub d = new AddAndSub();TA a = new TA();TB b = new TB();a.setName("线程A");b.setName("线程B");a.addAndSub = d;b.addAndSub = d;a.start();b.start();a.setPriority(Thread.MAX_PRIORITY);}
}
死锁了,进程 A 一直在等进程 B ,但 B 一直在等 A。
六、生产者与消费者实战案例
分析:有一个箱子,生产者生产牛奶,放入到箱子里面,消费者在箱子里面拿牛奶
示例
public class Box {private int milk = 0;private boolean state = false;public synchronized void put(int milk){if (state){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}this.milk = milk;System.out.println("放了" + this.milk + "瓶奶");state = true;notifyAll();}public synchronized void get(){if (!state){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}
// this.milk = milk;System.out.println("拿走了" + this.milk + "瓶奶");state = false;notifyAll();}}public class shengchan implements Runnable {private Box b;public shengchan(Box box) {this.b = box;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {b.put(i + 1);}}}public class xiaofei implements Runnable {private Box b;public xiaofei(Box box) {this.b = box;}@Overridepublic void run() {while (true) {b.get();}}
}public class Main {public static void main(String[] args) {Box box = new Box();shengchan shengchan = new shengchan(box);xiaofei xiaofei = new xiaofei(box);Thread threadA = new Thread(shengchan);Thread threadB = new Thread(xiaofei);threadA.start();threadB.start();}}
运行结果
七、图书推荐
内容简介
本书从 MATLAB 基础语法讲起,介绍了基于 MATLAB 函数的科学计算问题求解方法,实现了大量科学计算算法。
本书分为三大部分。第 1 章和第 2 章为 MATLAB 的基础知识,对全书用到的 MATLAB 基础进行了简单介绍。第 3 ~ 12 章为本书的核心部分,包括线性方程组求解、非线性方程求解、数值优化、数据插值、数据拟合与回归分析、数值积分、常微分方程求解、偏微分方程求解、概率统计计算及图像处理与信号处理等内容。第 13 ~ 15 章为实战部分,以实际生活中的数学问题为例,将前文介绍的各类科学计算算法应用其中。
本书内容全面、通俗易懂,适合有一定 MATLAB 基础、想要进行进阶学习的读者。
购买链接
相关文章:

JAVA进程和线程
哈喽~大家好呀,这篇来看看JAVA进程和线程。 🥇个人主页:个人主页 🥈 系列专栏:【日常学习上的分享】 🥉与这篇相关的文章: Redis快速入…...

JS自定义深浅度克隆
function deepClone(obj, cache new WeakMap()) {if (typeof obj ! object) return obj //普通类型,直接返回if (obj null) return objif (cache.get(obj)) return cache.get(obj)//防止循环引用,程序进入死循环if (obj instanceof Date) return new D…...

MySQL之表的约束
目录 表的约束1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键 表的约束 真正约束字段的是数据类型,数据类型规定了数据的用法、范围…假如我们没有按照其规定的约束,那么数据将插入不成功但是数据类型约束很单一,需要有一…...

Go基础——接口、并发
1、接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。接口可以让不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。Go 语言中的接口是隐式实现…...

zookeeper本地部署和集群搭建
zookeeper(动物园管理员)是一个广泛应用于分布式服务提供协调服务Apache的开源框架 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它 负责存储和管理大家都关心的数据 ,然 后 接受观察…...

优橙内推甘肃专场——5G网络优化(中高级)工程师
内推公司1:上海井胜通讯技术有限公司 内推公司2:西安长河通讯有限责任公司 内推公司3:沈阳电信工程局 上海井胜通讯技术有限公司 公司成立于2002年,是一家专业移动通信技术服务公司。2008年之前是香港一家大型流动通讯运营公司…...

crontab 定时任务
1.查看 crond 是否开启 systemctl status crond 2.设置 crontab 定时任务 基本语法 #基本语法 crontab [选项] 查看定时任务 #查看定时任务 crontab -l 编辑定时任务 #编辑定时任务 crontab -e 案例实操 */1 * * * * echo "hello,world" >> /root/hel…...

【入门Flink】- 03Flink部署
集群角色 Flik提交作业和执行任务,需要几个关键组件: 客户端(Client):代码由客户端获取并做转换,之后提交给JobManger JobManager:就是Fink集群里的“管事人”,对作业进行中央调度管理;而它获…...

DockerFile常用保留字指令及知识点合集
目录 DockerFile加深理解: DockerFile常用保留字指令 保留字: RUN:容器构建时需要运行的命令 COPY:类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 …...

怎么批量删除文件名中的空格?
怎么批量删除文件名中的空格?当我们整理文件的时候发现文件名里面有一些空格,如果空格较多,可能会造成文件名特别的长,我们一般会随手对文件进行重命名,然后将文件名中的空格删除掉,这项操作非常的简单方便…...

回顾十大数据恢复软件,帮助用于恢复丢失的文件!
您是否因丢失计算机上的重要文件而感到恐慌?你不是一个人!数据丢失是许多人面临的严重问题,但幸运的是,有许多解决方案可以恢复数据。 在本文中,我将回顾十大数据恢复软件,以帮助您恢复丢失的文件…...

【Linux】多路IO复用技术②——poll详解如何使用poll模型实现简易的一对多服务器(附图解与代码实现)
在阅读本篇博客之前,建议大家先去看一下我之前写的这篇博客,否则你很可能会一头雾水 【Linux】多路IO复用技术①——select详解&如何使用select模型在本地主机实现简易的一对多服务器(附图解与代码实现)http://t.csdnimg.cn/…...

CSS 滚动捕获 Scroll Snap
CSS 滚动捕获 Scroll Snap CSS 滚动捕获允许开发者通过声明一些位置(或叫作捕获位置)来创建精准控制的滚动体验. 通常来说轮播图就是这种体验的例子, 在轮播图中, 用户只能停在图 A 或者图 B, 而不能停在 A 和 B 的中间. 比如平时用淘宝或小红书, 当你上滑到下一个推荐内容时…...

【带头学C++】----- 三、指针章 ---- 3.9 数组作为函数的参数
当数组作为函数参数时,有几种常见的方式可以传递数组给函数: 数组作为指针传递: 数组名在函数调用时会自动转换为指向数组第一个元素的指针。通过指针可以访问数组元素,但无法获取数组的大小。在函数中修改指针指向的值会影响原始…...

完美处理 Android App 的 apk 输出路径与文件名
实现代码 buildTypes {// ...applicationVariants.all {variant ->variant.outputs.all {Calendar calendar Calendar.getInstance(Locale.CHINA);def buildDate String.format(Locale.CHINA, "%04d%02d%02d", calendar.get(Calendar.YEAR), calendar.get(Cale…...

【技术干货】开源库 Com.Gitusme.Net.Extensiones.Core 的使用
目录 1、项目介绍 2、为项目添加依赖 3、代码中导入命名空间 4、代码中使用 示例 1:string转换 示例 2:object转换 1、项目介绍 Com.Gitusme.Net.Extensiones.Core是一个.Net扩展库。当前最新版本1.0.4,提供了常见类型转换,…...

大厂面试题-b树和b+树的理解
为了更清晰的解答这个问题,从三个方面来回答: a.了解二叉树、AVL树、B树的概念 b.B树和B树的应用场景 1.B树是一种多路平衡查找树,为了更形象的理解,我们来看这张图。 二叉树,每个节点支持两个分支的树结构ÿ…...

NeRF-SLAM部署运行(3060Ti)
记录在部署运行期间遇到的一些问题,分享给大家~ 一、环境 RTX 3060 Ti、8G显存、Ubuntu18.04 二、部署 1. 下载代码 git clone https://github.com/jrpowers/NeRF-SLAM.git --recurse-submodules git submodule update --init --recursive cd thirdparty/insta…...

零基础编程入门教程软件推荐,零基础编程自学
零基础编程入门教程软件推荐,零基础编程自学 给大家分享一款中文编程工具,零基础轻松学编程,不需英语基础,编程工具可下载。 这款工具不但可以连接部分硬件,而且可以开发大型的软件,象如图这个实例就是用…...

Amazon EC2 安全可调用的云虚拟主机服务器
💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Amazon EC2 打造全新的科技链 Amazon Elastic Compute Cloud(Amazon EC2)提供最广泛、最深入的计算平台,拥有超过 500 个实例&…...

HTTP/HTTPS、SSL/TLS、WS/WSS 都是什么?
有同学问我,HTTP/HTTPS、SSL/TLS、WS/WSS 这都是些什么?那我们就先从概念说起: HTTP 是超文本传输协议,信息是通过明文传输。HTTPS 是在 HTTP 的基础上信息通过加密后再传输。SSL 是实现 HTTPS 信息传输加密的算法。TLS 是 SSL 的…...

软考之系统安全理论基础+例题
系统安全 系统安全性分析与设计 作为全方位的、整体的系统安全防范体系也是分层次的,不同层次反映了不同的安全问题,根据网络的应用现状情况和结构,可以将安全防范体系的层次划分为 物理层安全系统层安全网络层安全应用层安全安全管理。 …...

棱镜七彩亮相工控中国大会,以软件供应链安全助力新型工业化高质量发展
2023年11月1日-3日,2023第三届工控中国大会在苏州国际会议中心举办,本届大会由中国电子信息产业发展研究院、中国工业经济联合会、国家智能制造专家委员会、国家产业基础专家委员会、江苏省工业和信息化厅、江苏省国有资产监督管理委员会、苏州市人民政府…...

数据可视化:动态柱状图
终于来到最后一个数据可视化的文章拿啦~~~ 在这里学习如何绘制动态柱状图 我先整个活 (๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤ 什么是pyecharts? 答: Python的Pyecharts软件包。它是一个用于Python数据可视化和图表绘制的库,可用于制作…...

vue3 自定义loading
使用antdv 后发现只有button支持loaidng属性,而其他元素不能使用loading来显示是否加载中,需要套一层 a-spin 才能支持,非常不方便。 所以写了个自定义的指令来进行处理 新建loading.vue文件用来页面显示 <template><div class&q…...

Ceph-deploy跳过gpg-key验证(离线环境安装Ceph)
问题 CentOS-7.6.1810离线环境搭建Ceph环境时出现gpg-key安装源公钥检查错误。原因是执行ceph-deploy install 命令的服务器无法访问互联网。具体报错如下图: 解决 安装命令后新增--no-adjust-repos参数即可跳过安装 GPG 密钥。 命令如下: ceph-deplo…...

想入行单片机开发的学生们的忠告
想入行单片机开发的学生们的忠告 做嵌入式单片机开发十来年。想给那些想入行单片机开发的同学一些建议。 1.想做这行,做好坚持学习的准备。最近很多小伙伴找我,说想要一些单片机的资料,然后我根据自己从业十年经验,熬夜搞了几个通…...

【番外篇】C++语法学习笔记
学习目标:C的一些高级操作 根据C菜鸟教程自学的笔记,大家有想学习C的话可以根据这个网站进行学习。这个推荐有一定基础的再去进行自学。新手的话还是建议直接看一些视频跟着学 学习内容: 1. 运算符重载 说到C中的运算符重载,首…...

js 字符串转数字
在 JavaScript 中,可以使用以下方法将字符串转换为数字: parseInt parseInt():将字符串转换为整数。它会从字符串的开头开始解析,直到遇到非数字字符为止。如果第一个字符不能转换为数字,则返回 NaN。 let str &qu…...