当前位置: 首页 > news >正文

JavaEE——多线程1(超详细版)

目录

基础理论知识:

进程(process):

1.如何管理进程:

2.PCB(进程控制块):

线程(Thread):

一.创建线程

1.继承thread类

2.实现Runnable接口

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

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

5.使用lambda表达式创建Runnable子类对象

二.Thread常用的构造方法

三.Thread的几个常见属性

四.启动一个线程--start()

五.中断一个进程(两种方式)

1.通过共享标志位进行沟通通知

2.调用Interrupt()方法来通知

六.等待一个进程--join()

七.获取当前线程引用

八.休眠当前线程--sleep()

线程的状态


基础理论知识:

1.冯.诺依曼体系结构

cpu(中央处理器)(可用各种算术运算,逻辑判断的“通用计算机芯片”),存储器(硬盘 ,内存...),输入设备(键盘,鼠标...),输出设备(显示器...)

硬盘和内存对比:

硬盘:读写速度慢,存储空间大,成本低,断电不丢失数据

内存:读写速度快,存储空间小,成本高,断电丢失数据

2.指令:指导CPU进行工作的命令

一条指令(程序)执行过程:

a.读取指令

b.解析指令

c.执行指令

3.寄存器:在CPU上存储数据的模块(CPU存储数据实际是通过寄存器)(在CPU上执行指令,进行各种运算存储临时数据)

CPU的寄存器和内存的对比:

CPU寄存器·:读写速度快,存储空间小,成本高,断电丢失数据

内存:读写速度慢,存储空间大,成本低,断电丢失数据

进程(process):

一个运行起来的程序

1.如何管理进程:

使用结构体,进程控制块(PCB),将多个进程组织起来

2.PCB(进程控制块):

a.pid(进程id):进程标识符

b.内存指针:进程需要知道需要执行的指令在哪,指令依赖的数据又在哪

我们可以得出:进程运行过程中,需要依赖内存资源

c.文件描述符表:进程运行,依赖到网盘 ,网卡等相关资源;进程运行,执行指令,依赖CPU,也消耗CPU资源

我们又可以得出结论:进程是操作系统资源分配的基本单位

以下也是进程调度

d.进程状态(这里只提到了两个)

--》就绪状态:随叫随到

--》阻塞状态:进程当前不适合在CPU上执行

e.进程优先级:有些进程,优先级更高,可以得到的CPU资源更多

f.进程上下文:保存上下文  恢复上下文

g.进程的记账信息

线程(Thread):

可以说是轻量级的进程,一个线程就是一个“执行流”

1.为什么要用线程

a.“并发编程”成为刚需

b.线程比进程更轻量:创建线程比创建进程更快,销毁线程比销毁进程更快,调度线程比调度进程更快

!!!2.进程和线程的区别!!!

A.进程是包含线程的(每个进程至少含有一个线程,即主线程)

B.进程与进程之间是不共享资源空间的,同一个进程的多个线程之间是共享同一个资源空间的

C.进程是操作系统资源分配的最小单位,线程是操作系统调度的最小单位

D.一个进程挂了不会影响其他进程,同一个进程的一个线程挂了会一并带走其他线程(整个进程崩溃

一.创建线程

1.继承thread类

要子类重写父类run方法

package Thread;import static java.lang.Thread.sleep;public class demo {//第二个线程public static class mythread extends Thread{@Overridepublic void run() {//子类对父类方法的重写while(true){System.out.println("这是一个thread线程...");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}//主线程public static void main(String[] args) {mythread thread=new mythread();//向上转型thread.start();//真正创建了一个线程while (true){System.out.println("这是一个主线程...");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

2.实现Runnable接口

需要重写run方法

package Thread;import static java.lang.Thread.sleep;public class demo2 {public static class myrunnnable implements Runnable{@Overridepublic void run() {while (true) {System.out.println("这是一个runnable实现的线程");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}public static void main(String[] args) {//方式一Thread thread=new Thread(new myrunnnable());//方式二// Runnable runnable=new myrunnnable();//Thread thread=new Thread(runnable);thread.start();while (true){System.out.println("这是一个mian线程...");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

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

package Thread;import static java.lang.Thread.sleep;public class dome3 {public static void main(String[] args) {Thread thread=new Thread() {@Overridepublic void run() {while (true) {System.out.println("这是匿名内部类创建thread子类对象实现的线程");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};thread.start();while (true) {System.out.println("这是mian实现的线程");try {thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

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

package Thread;public class dome4{public static void main(String[] args) {Thread thread=new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("这是匿名内部类创建Runnable子类对象实现的线程");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});thread.start();while (true) {System.out.println("这是mian实现的线程");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}

5.使用lambda表达式创建Runnable子类对象

package Thread;public class dome5 {public static void main(String[] args) {//()->{}创建了一个匿名函数式接口的子类,并创建对应的实例,重写里面的方法Thread thread=new Thread(()->{ while(true) {System.out.println("函数式接口调用");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.start();while (true) {System.out.println("这是mian实现的线程");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

二.Thread常用的构造方法

1.Thread()//创建线程对象

2.Thread(Runnable target)//使用Runnable接口创建子类对象

3.Thread(String name)//创建线程对象,并命名

4.Thread(Runnable target,String name)//使用Runnable接口创建子类对象,并命名

三.Thread的几个常见属性

ID                          获取方法:getId()

名称                      获取方法:getName()

状态                      获取方法:getState()

优先级                   获取方法:getPriority()

是否后台线程        获取方法:isDaemon()

什么是前台线程?什么是后台线程?

前台线程可以理解为  自己创建的线程和main主线程;可以用setDaemon方法去修改;前台线程有多个时,全部结束,线程结束

后台线程可以理解为  除了前台线程的线程,不影响线程的结束

JVM会在一个进程中的所有非后台线程结束后,才会结束运行

是否存活                获取方法:isAlive()

可以理解为run方法是否运行结束

是否中断                获取方法:isInterrupt()

四.启动一个线程--start()

是JVM提供的方法,本质是调用操作系统的API

调用start才是在操作系统底层中创建了一个线程

!!!一个Thread对象只能start一次!!!

五.中断一个进程(两种方式)

也可以理解为终止一个进程,就是让线程的入口方法尽快结束

1.通过共享标志位进行沟通通知

package Thread;public class dome6 {public static volatile boolean flag=false;public static void main(String[] args) {Thread thread=new Thread(()->{while(!flag) {System.out.println("这个线程正在进行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.start();try {Thread.sleep(1000*5);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("不能运行了,累了...");flag=true;}
}

2.调用Interrupt()方法来通知

package Thread;public class demo7 {public static void main(String[] args) {Thread thread=new Thread(()->{while(!Thread.interrupted()) {System.out.println("这个线程正在进行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.start();try {Thread.sleep(1000*5);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("不能运行了,累了...");Thread.interrupted();}}

思考:为什么代码又继续运行了呢?

是因为异常引起的,当我们调用sleep/wait/join方法,会以异常的方式通知,清除中断标志位,所以,取决于我们在处理异常的时候,关键在于catch代码块

如下代码:

package Thread;public class demo7 {public static void main(String[] args) {Thread thread=new Thread(()->{while(!Thread.currentThread().isInterrupted()) {//while(Thread.interrupted()){//两种方法都可以System.out.println("这个线程正在进行...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();break;//break;            立即结束//什么也不写          不终止//写其他逻辑再break   稍后终止}}});thread.start();try {Thread.sleep(1000*5);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("不能运行了,累了...");thread.interrupt();}
}

六.等待一个进程--join()

可以理解为多个线程,线程结束的先后顺序

package Thread;public class demo8 {public static void main(String[] args) {Thread thread1 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("线程1在运行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("线程2在运行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread1.start();thread2.start();thread.join();thread.join();}
}

我们使用再次使用join方法的正确位置后再观察(先start再join)

package Thread;public class demo8 {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("线程1在运行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("线程2在运行...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread1.start();thread1.join();thread2.start();thread2.join();}
}

同时,join()在括号中也可以添加参数,避免死等的情况(即超时等待)

七.获取当前线程引用

public static Thread currentThread()返回当前线程对象的引用

八.休眠当前线程--sleep()

实际休眠时间大于等于设置参数的时间(由于CPU的调度)

它是Thread类中的方法,可以进行超时等待

线程的状态

1.NEW:安排了⼯作,还未开始行动(也可以理解为new一个对象,但是没有进行start操作)

2. RUNNABLE:可⼯作的,又可以分成正在⼯作中和即将开始⼯作(也可以理解为就绪状态 a.正在CPU上工作  b.随时准备到CPU上工作)

3. BLOCKED:这⼏个都表示排队等着其他事情(由于锁导致的阻塞)

4. WAITING:这⼏个都表示排队等着其他事情(没有超时的等待(死等))

5. TIMED_WAITING:这⼏个都表示排队等着其他事情(指定时间的阻塞(线程阻塞不参与CPU的调度),超时等待)

6. TERMINATED:⼯作完成了(可以理解为线程结束了,但是thread对象还在)

!!!前面学到的isAlive()可以理解为不是new和terminated状态都是活着的!!!

多线程内容,先到这里,有问题欢迎评论区留言讨论,请同学们多多练习相关知识!!!看我后续内容

http://www.dtcms.com/a/557571.html

相关文章:

  • 工信部网站备案举报比较好的网站开发教学网站
  • 有设计感的网站东莞网站搜索排名
  • 网站建设 设计那种连接线厂家上海网站推荐
  • 公司网站最新版班级网站怎么做ppt
  • 远程调用 - OpenFeign
  • 简述电子商务网站的建设步骤酷炫的网站模板免费下载
  • 【车载开发系列】常见集成测试的方法
  • Java 异常处理机制专项优化
  • 外设模块学习(12)——SW-520D倾斜传感器、SW-420震动传感器、声音传感器(三引脚)(STM32代码参考)
  • 行业网站解决方案wordpress主题点赞
  • 微网站的特点模板之家html5
  • 模电基础和数电基础
  • 企业免费网站模板企业宣传册范例
  • 神经网络组植物分类学习规划与本周进展综述13
  • 生产管理系统详解:10 张表覆盖“下单→设计→生产→采购→出入库→售后”全链路,字段与流程图节点一一对应,直接建库即可使用
  • 炒币网站开发网站建设项目经验
  • 论坛类网站开发报价wordpress官方主题下载地址
  • 安路FPGA_LED闪烁
  • 徐州模板开发建站营销型网站设计公司哪里有
  • C# 进程管理实战:检查与启动EXE程序的完整指南
  • ssm面试六十题
  • 做网站内容需要自己填的吉安做网站
  • C# 使用 CSRedisCore指南
  • AD域 BloodHound 2025最新Linux穩定版|Docker封鎖繞過安裝脚本
  • 基于单片机的高频感应加热式棉花糖机的电气控制系统的设计(论文+源码)
  • C++:模板的幻觉 —— 实例化、重定义与隐藏依赖势中
  • 国外市场网站推广公司毕业设计做网站大小有什么要求
  • 【LUT技术专题】SVDLUT代码讲解
  • 基于多模态特征提取与贝叶斯优化的污染源智能识别与分类系统
  • 将遥感数据处理成dfine可以处理的数据