JUC并发编程基础(包含线程概念,状态等具体实现)

一.JUC并发编程基础

1. 并行与并发

1.1 并发:

  1. 是在同一实体上的多个事件
  2. 是在一台处理器上"同时处理多个任务"
  3. 同一时刻,其实是只有一个事件在发生.

即多个线程抢占同一个资源.
在这里插入图片描述

1.2 并行

  1. 是在不同实体上的多个事件
  2. 是在多台处理器上同时处理多个任务
  3. 同一时刻,大家都在做事情.你做你的,我做我的.

即多个线程同时执行.

在这里插入图片描述

2. 进程,线程,管程

2.1 进程

在系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源.

2.2 线程

也被叫做轻量级进程,在同一个进程内会有1个或多个线程,是大多数操作系统进行时序调度的基本单元

2.3 管程

也被称为Monitor(监视器),也就是平时我们所说的锁.

3. 线程启动的三种方式

3.1 继承Thread类.重写run方法

继承重写

    public class MyThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}}

执行

    public class ExtendThreadMain {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();}}

注意:启动线程是调用父类的start方法,而不是直接去调用run方法.

3.2 实现Runable接口

实现重写

    public class MyThread implements Runnable{@Overridepublic void run() {for(int i=0;i<10;i++){System.out.println(Thread.currentThread().getName()+":"+i);}}}

主函数启动线程

    public class RunnableThreadMain {public static void main(String[] args) {MyThread myThread = new MyThread();Thread t1 = new Thread(myThread);t1.start();}}

当然我们还有另外一种写法

注意到Thread的构造方法的参数有
在这里插入图片描述

里面存在一个Runnable参数和一个线程名的两个参数的方法.熟悉静态内部类或者Lamba表达式的应该了解,这里完全可以利用这种特性来启动线程,所以我们可以这样改写.

public class RunnableThreadMain {public static void main(String[] args) {//        MyThread myThread = new MyThread();//        Thread t1 = new Thread(myThread);Thread t1 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}, "t1");t1.start();}}

3.3 实现Callable接口

实现重写call方法(其实也就跟上述两个的run方法的作用一样)

    /*** 这里的泛型指的是call方法的返回值*/public class MyThread implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i < 100; i++) {sum+=i;}return sum;}}

主函数调度,这里与其他两种实现不同的是,可以有返回值,这里引用了FutureTask接口来接收这个值

    public class CallableThreadMain {public static void main(String[] args) throws ExecutionException, InterruptedException {MyThread myThread = new MyThread();FutureTask<Integer> futureTask = new FutureTask<>(myThread);Thread t1 = new Thread(futureTask);t1.start();Integer sum = futureTask.get();System.out.println("sum = " + sum);}}

注意:get方法时,方法会阻塞,直到这个线程执行完毕有返回值,代码才会往下进行.

4. 守护线程

守护线程

  • 守护线程是一种特殊的线程,它并不属于用户线程,也不受用户线程的控制,但它却有着特殊的重要性。
  • 守护线程的主要目的是为其他非守护线程提供服务。当所有的用户线程都结束时,守护线程也会随之结束
  • 守护线程的创建方式是在启动线程时调用Thread.setDaemon(true)方法,该方法将线程设置为守护线程。
  • 判断当前线程是否为守护线程调用 Thread.currentThread().isDaemon()方法,true为是,false为不是

守护线程的退出条件是:

  1. 所有用户线程都结束;
  2. 调用了Thread.stop()方法;
  3. 调用了Runtime.exit()方法。

注意:

  1. 守护线程只能有一个,一个JVM中只能有一个守护线程;
  2. 守护线程不能执行用户线程的run()方法,因为它没有用户线程可执行;
  3. 守护线程的优先级比较低,它只会在JVM中运行,不会影响到其他线程的运行;
  4. 守护线程的异常处理方式和非守护线程相同。
    public class ProtectThread {public static void main(String[] args) {//创建一个线程Thread t1 = new Thread(() -> {System.out.println(Thread.currentThread().getName() + ": " +(Thread.currentThread().isDaemon() ? " 守护线程" : "用户线程"));while (true) {}},"t1");t1.setDaemon(true);//设置为守护线程t1.start();System.out.println(Thread.currentThread().getName() + ": " +(Thread.currentThread().isDaemon() ? " 守护线程" : "主线程"));}}

5. windows,linux下查看和杀死进程

5.1windows

  • 任务管理器可以查看进程和线程数,也可以用来杀死进程.

  • tasklist 查看进程
    在这里插入图片描述

  • taskkill 杀死进程

    • 通常带两个参数 /F 强制杀死 /PID 进程id

5.2 linux

  • ps -ef 查看所有进程
    在这里插入图片描述

  • ps -fT -p 查看某个进程(PID)的所有线程

在这里插入图片描述

  • kill 杀死进程
  • top按大写H切换是否显示线程

动态展示所有进程占用cpu的情况
在这里插入图片描述

  • top -H -p 查看某个进程(PID)的所有线程

5.3 查看Java的进程

  • jps 命令查看所有 Java进程

  • jstack 查看某个Java进程 (PID) 的所有线程状态.
    在这里插入图片描述

  • jconsole 来查看某个Java进程中线程的运行情况(图形界面)
    在这里插入图片描述

6. 线程运行原理

我们知道JVM虚拟机中有栈和堆两块内存区域.

而每一个线程都有属于自己的栈区,每个线程直接的栈互不干扰,线程中每一个方法都是一个栈帧.

看如下这段代码的调度过程:
在这里插入图片描述

我们再通过一幅图来理解

在这里插入图片描述

7. 线程的上下文切换

有些时候由于一些原因,当线程在执行时,cpu被其他线程抢占到也就是说存在线程之间的切换的过程,我们称为上下文切换.

哪些原因会导致线程上下文切换呢

  • 线程的cpu时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了sleep,yield,wait,join,park,synchronized,lock等方法

当上下文切换时,需要由操作系统去保存当前线程的状态,也就是记录其中的一些变量啊,执行到哪一步啦,并恢复另一个线程的状态,Java中对应的概念就是程序计数器,它的作用是记住下一条JVM指令的执行地址,是线程自己私有的

  • 状态包括程序计数器,虚拟机栈中每个栈帧的信息,如局部变量,操作数栈,返回地址

注意:频繁的上下文切换会影响性能.

8. 线程的几种状态

8.1 五种(来源于操作系统)

在这里插入图片描述

  • 初始状态: 相当于我们刚刚new出来一个线程对象.仅是在语言层面创建了线程对象,还并未与操作系统线程相关联.
  • 可运行状态(就绪状态) : 指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行.也就是都准备去抢占cpu啦,如果抢到了就会进入运行状态
  • 运行状态: 指获取了CPU时间片运行中的状态.
    • 当CPU时间片用完会从运行状态转换至就绪状态, 会导致线程的上下文切换
  • 阻塞状态
    • 如果调用了阻塞的API,例如BIO(同步阻塞IO)读写文件,这时该线程不会用到CPU,会导致线程上下文切换,进入阻塞状态.
    • 等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至可运行状态.
    • 与可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器一直不会考虑调度它们.

可以这样理解: 好比去上厕所,你抢到厕所的使用权啦,但是突然你又不想上啦,想起还有其他事情要做,总不能占着茅坑不拉屎叭,所以cpu,也就是厕所,你得离开这里,这个时候你去干其他的事都可以,等你忙完又想上厕所啦,这个时候又和别人一样需要有机会才能抢到厕所的使用权,也就是重新回到就绪状态.

  • 终止状态: 表示线程已经执行完毕,生命周期已经结束,不会在转换为其他状态.也就是代码执行完毕,没有循环的包裹,执行完就会进入终止状态.

8.2 六种(Java层面)

我们来查看Thread类当中的一个枚举类State
在这里插入图片描述
所以一共有六种状态,其具体为
在这里插入图片描述

  • NEW 线程刚被创建,但是还没有调用start()方法
  • RUNNABLE当调用了start()方法之后.

注意: JavaAPI层面的RUNNABLE状态涵盖了操作系统层面的可运行状态(就绪状态),运行状态,阻塞状态(由于BIO导致的线程阻塞,在Java里无法区别,仍然认为是可运行,也就是RUNNABLEZ状态)

  • BLOCKED 可以理解为抢占锁时未抢到,造成阻塞等待
  • WAITING 等待别的线程执行结束
  • TIMED_WATING 有时间的等待,也就是对应Thread.sleep();
  • TERMINATED 当线程代码运行结束
8.2.1 代码实现每种状态
  • NEW (创建线程不开始)
    在这里插入图片描述

  • RUNNABLE(就绪,运行,阻塞(操作系统的层面例如IO流时))
    在这里插入图片描述

  • TERMINATED (代码执行完毕就进入此状态)
    在这里插入图片描述

  • TIMED_WATING (睡眠时进入)
    在这里插入图片描述

  • WAITING(利用join方法,使线程2等待线程1执行完毕,此时状态为WAITING)
    在这里插入图片描述

  • BLOCKED(阻塞,抢占锁失败,阻塞等待)
    在这里插入图片描述

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

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

相关文章

【C++】main函数及返回值深度解析

一.main函数介绍 1.main函数怎么写 #include <iostream>int main() {// 程序的代码放在这里std::cout << "Hello, World!" << std::endl;return 0; }在这个例子中&#xff1a; #include <iostream> 是预处理指令&#xff0c;它告诉编译器…

在昇腾服务器上使用llama-factory对baichuan2-13b模型进行lora微调

什么是lora微调 LoRA 提出在预训练模型的参数矩阵上添加低秩分解矩阵来近似每层的参数更新&#xff0c;从而减少适配下游任务所需要训练的参数。 环境准备 这次使用到的微调框架是llama-factory。这个框架集成了对多种模型进行各种训练的代码&#xff0c;少量修改就可使用。 …

小红书矩阵系统源码:赋能内容创作与电商营销的创新工具

在内容驱动的电商时代&#xff0c;小红书凭借其独特的社区氛围和用户基础&#xff0c;成为品牌营销和个人创作者不可忽视的平台。小红书矩阵系统源码&#xff0c;作为支撑这一平台的核心技术&#xff0c;提供了一系列的功能和优势&#xff0c;助力用户在小红书生态中实现更高效…

Windows 安装hadoop 3.4

目录 安装 下载 设置环境变量 配置 修改&#xff1a;hadoop-env.cmd 修改&#xff1a;core-sit.xml 修改&#xff1a;hdfs-site.xml 修改&#xff1a;mapred-site.xml 修改&#xff1a;yarn-site.xml 运行 格式化HDFS文件系统 启动&#xff1a;hadoop 启动&#xf…

python-21-零基础自学python 写了一个彩票 发现买彩票中了真的是天选

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版 知识点&#xff1a; from random import choice、choice&#xff08;&#xff09;函数用法、while循环 练习内容&#xff1a; 练习9-14&#xff1a;彩票 创建一个列表或元组&#xff0c;其中包含10个数…

JAVA基础知识(上)

# 一、说说&和&&的区别? 作为运算符&#xff1a;& 将二进制的每一位进行与运算 作为逻辑运算符&#xff1a;两者都是与&#xff0c;&& 如果左边为假则终止右边运算&#xff0c;即短路运算。& 则需要把两边的比较执行完 # 二、int和Integer的区…

Steam平台的辉煌轨迹:数字游戏革命的领航者

在数字世界的浩瀚星空中&#xff0c;有一颗恒星以其耀眼的光芒照亮了无数游戏爱好者的道路&#xff0c;它就是Valve公司的杰作——Steam平台。自2003年横空出世以来&#xff0c;Steam不仅颠覆了传统游戏分发的模式&#xff0c;更以其卓越的创新能力和前瞻性的战略眼光&#xff…

CSS - 深入理解选择器的使用方式

CSS基本选择器 通配选择器元素选择器类选择器id 选择器 通配选择器 作用&#xff1a;可以选中所有HTML元素。语法&#xff1a; * {属性名&#xff1b;属性值; }举例&#xff1a; /* 选中所有元素 */ * {color: orange;font-size: 40px; }在清除样式方面有很大作用 元素选择器…

JAVA基础知识(下)

一、String相关面试题 1. 为什么 String 在 java 中是不可变的? - 如果不是不可变的&#xff1a;这种情况根本不可能&#xff0c;因为在字符串池的情况下&#xff0c;一个字符串对象/文字&#xff0c;例如 “Test” 已被许多参考变量引用&#xff0c; 因此如果其中任何一个更…

ubuntu下载Nginx

一、Nginx下载安装&#xff08;Ubuntu系统&#xff09; 1.nginx下载 sudo apt-get install nginx2.nginx启动 启动命令 sudo nginx重新编译(每次更改完nginx配置文件后运行&#xff09;&#xff1a; sudo nginx -s reload3.测试nginx是否启动成功 打开浏览器访问本机80端口…

小酌消烦暑|人间正清欢

小暑是二十四节气之第十一个节气。暑&#xff0c;是炎热的意思&#xff0c;小暑为小热&#xff0c;还不十分热。小暑虽不是一年中最炎热的时节&#xff0c;但紧接着就是一年中最热的节气大暑&#xff0c;民间有"小暑大暑&#xff0c;上蒸下煮"之说。中国多地自小暑起…

openssh版本升级实战(修补ssh漏洞)基于RedHat8.4版本测试--已成功升级

升级前具有漏洞的的版本 通过命令查看目前系统的ssh和sshd版本&#xff1a; ssh -V sshd -V 注意&#xff1a;由于ssh是远程连接服务器的功能&#xff0c;在进行下面操作升级openssh前&#xff0c;请打开多个连接会话保持&#xff0c;如升级失败&#xff0c;可通过已连接的会话…

antd实现简易相册,zdppy+vue3+antd实现前后端分离相册

前端代码 <template><a-image:preview"{ visible: false }":width"200"src"http://localhost:8889/download/1.jpg"click"visible true"/><div style"display: none"><a-image-preview-group:previe…

粤港澳大湾区人工智能资本对接会”成功举办!

为促进惠州仲恺高新区人工智能产业的发展&#xff0c;推动惠深两地产业资源深度协同与合作&#xff0c;也为吸引更多的优质项目与投融资机构为惠州仲恺高新区产业发展注入动力&#xff0c;加速深圳人工智能相关产业资源落地仲恺。2024年06月26日&#xff0c;由仲恺高新区科技创…

UE5 视频播放(自动播放和自动清除MediaTexture)

媒体播放器的打开时播放和媒体纹理的自动清除 。 在UE5开发视频播放时&#xff0c;遇到了闪帧的现象。合理选择这两个功能可解决。

小阿轩yx-LVS+Keepalived群集

小阿轩yx-LVSKeepalived群集 Keepalived 双机热备份基础知识 起初是专门针对 LVS 设计的一款强大的辅助工具主要用来提供故障切换(Failover)和健康检査(HealthChecking)功能—判断LVS 负载调度器、节点服务器的可用性当 master 主机出现故障及时切换到backup 节点保证业务正常…

动手学深度学习(Pytorch版)代码实践 -循环神经网络-51序列模型

51序列模型 import torch from torch import nn from d2l import torch as d2l import matplotlib.pyplot as pltT 1000 # 总共产生1000个点 time torch.arange(1, T 1, dtypetorch.float32) x torch.sin(0.01 * time) torch.normal(mean0, std0.2, size(T,)) d2l.plot(…

ERROR | Web server failed to start. Port 8080 was already in use.

错误提示&#xff1a; *************************** APPLICATION FAILED TO START ***************************Description:Web server failed to start. Port 8080 was already in use.Action:Identify and stop the process thats listening on port 8080 or configure thi…

2024年特种设备(电梯作业)题库考试题库

1.直接作用式液压电梯轿厢与柱塞&#xff08;缸筒&#xff09;之间的连接应为&#xff08;&#xff09;。 A.刚性连接 B.固定连接 C.法兰连接 D.挠性连接 答案&#xff1a;D 2.正常情况下&#xff0c;当电磁式继电器线圈得电时&#xff0c;其常开触点将&#xff08;&…

二进制求和、字符串相加-sting类题型

67. 二进制求和 - 力扣&#xff08;LeetCode&#xff09; 两个题目方法完全一样 用两个数据的末尾位相加&#xff0c;从末尾位开始逐位相加&#xff0c;记录进位&#xff1b; class Solution { public:string addBinary(string a, string b) {int end1 a.size() - 1;int end…