JUC并发编程基础(包含线程概念,状态等具体实现)
一.JUC并发编程基础
1. 并行与并发
1.1 并发:
- 是在同一实体上的多个事件
- 是在一台处理器上"同时处理多个任务"
- 同一时刻,其实是只有一个事件在发生.
即多个线程抢占同一个资源.
1.2 并行
- 是在不同实体上的多个事件
- 是在多台处理器上同时处理多个任务
- 同一时刻,大家都在做事情.你做你的,我做我的.
即多个线程同时执行.
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为不是
守护线程的退出条件是:
- 所有用户线程都结束;
- 调用了Thread.stop()方法;
- 调用了Runtime.exit()方法。
注意:
- 守护线程只能有一个,一个JVM中只能有一个守护线程;
- 守护线程不能执行用户线程的run()方法,因为它没有用户线程可执行;
- 守护线程的优先级比较低,它只会在JVM中运行,不会影响到其他线程的运行;
- 守护线程的异常处理方式和非守护线程相同。
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(阻塞,抢占锁失败,阻塞等待)
相关文章:

JUC并发编程基础(包含线程概念,状态等具体实现)
一.JUC并发编程基础 1. 并行与并发 1.1 并发: 是在同一实体上的多个事件是在一台处理器上"同时处理多个任务"同一时刻,其实是只有一个事件在发生. 即多个线程抢占同一个资源. 1.2 并行 是在不同实体上的多个事件是在多台处理器上同时处理多个任务同一时刻,大家…...

集中管理和分析日志:使用 ELK 套件构建强大的日志管理平台
集中管理和分析日志:使用 ELK 套件构建强大的日志管理平台 日志是监控和调试应用程序和系统的重要工具。集中管理和分析日志可以帮助你快速定位问题、了解系统运行状况和性能,并提高你的日志管理效率。ELK 是一个流行的日志管理解决方案,由 …...

深度学习 - 模型的保存与部署方式汇总
深度学习模型保存和加载格式科普 在深度学习中,模型的保存和加载是非常重要的环节。不同的格式有不同的特点和适用场景。本文将为新手朋友们介绍几种常见的模型格式,包括它们的简介、保存方式、加载方式、优缺点以及应用场景。 1. PyTorch (.pth, .pt)…...

人工智能对网络安全有何影响?
人工智能网络安全在短期、中期和长期如何变化 当今数字时代网络安全的重要性 在谈论人工智能在网络安全中的作用时,必须首先考虑短期影响,因为它们是最明显的,而且它是一个未知的领域,需要超越直接炒作的能力。 因此࿰…...

Oracle的RECYCLEBIN回收站:轻松恢复误删对象
目录 Oracle的RECYCLEBIN回收站:轻松恢复误删对象一、概念二、工作原理三、使用方法1 查看回收站中的对象2 恢复回收站中的对象2.1 恢复表(TABLE)2.2 恢复索引(INDEX)2.3 恢复视图(VIEW)2.4 恢复…...

Android 内存原理详解以及优化(二)
上一篇讲了内存原理,如果还没看可以先看上一篇:Android 内存原理详解以及优化(一) 这一篇我总结一下我们经常遇到的内存优化问题: 1.内存抖动 自定义view的ondraw是会被频繁调用的,那在这个方法里面就不能频…...

Shell学习——Shell变量
文章目录 Shell变量使用变量只读变量删除变量变量类型字符串变量: 在 Shell中,变量通常被视为字符串。整数变量: 在一些Shell中,你可以使用 declare 或 typeset 命令来声明整数变量。数组变量: Shell 也支持数组&#…...

Java中的持续集成与持续部署(CI/CD)
Java中的持续集成与持续部署(CI/CD) 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中的持续集成(Co…...

极狐GitLab 将亮相2024空天信息大会暨数字地球生态峰会,携手中科星图赋能空天行业开发者
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…...

Beats:使用 Filebeat 从 Python 应用程序中提取日志
本指南演示了如何从 Python 应用程序中提取日志并将其安全地传送到 Elasticsearch Service 部署中。你将设置 Filebeat 来监控具有标准 Elastic Common Schema (ECS) 格式字段的 JSON 结构日志文件,然后你将在 Kibana 中查看日志事件发生的实时可视化。虽然此示例使…...

51单片机第23步_定时器1工作在模式0(13位定时器)
重点学习51单片机定时器1工作在模式0的应用。 在51单片机中,定时器1工作在模式0,它和定时器0一样,TL1占低5位,TH1占高8位,合计13位,也是向上计数。 1、定时器1工作在模式0 1)、定时器1工作在模式0的框图…...

linux的服务管理
systemd systemd 是一个系统和服务管理器,用于Linux操作系统中,旨在替代传统的Unix系统V初始化系统(SysV init)。 不一定所有使用 yum 安装的软件都可以通过 systemctl start 来管理。能否通过 systemctl start 管理取决于软件包…...

动手学深度学习(Pytorch版)代码实践 -循环神经网络-53语言模型和数据集
53语言模型和数据集 1.自然语言统计 引入库和读取数据: import random import torch from d2l import torch as d2l import liliPytorch as lp import numpy as np import matplotlib.pyplot as plttokens lp.tokenize(lp.read_time_machine())一元语法…...

Python 学习之自动化运维技术(八)
Python 的自动化运维技术 Python的自动化运维技术是指利用Python编程语言和相关工具实现运维工作的自动化,以提高效率、减轻工作负担。以下是对Python自动化运维技术的清晰归纳和详细介绍: 一、自动化运维的核心优势 ● 提高效率:通过自动化脚…...

【python】PyQt5可视化开发,如何设计鼠标显示的形状?
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

利用大模型知识库,优化智能客服问答效果 | 创新场景
ITValue 痛点 SSC( Share Service Center ,共享服务中心)是企业日常接触最多的场景之一,更多是对内服务,包括 HR 、财务、IT 等。该场景对专业度要求非常高,知识点非常多,对于知识的使用者或者查…...

物联网协议都包含哪些协议?
物联网协议是物联网生态系统中不可或缺的组成部分,它们负责处理和协调物联网设备之间的通信。具体介绍如下: Ethernet:以太网是一种有线网络协议,广泛应用于局域网络(LAN)中,提供稳定的高速数据传输。Wi-Fi࿱…...

面试专区|【52道微服务架构高频题整理(附答案背诵版)】
简述什么是微服务? 微服务是一种软件架构风格,它将应用程序拆分成一系列小型、独立的服务,每个服务都运行在其自己的进程中,通过轻量级通信机制进行通信。每个服务都具有明确的业务能力,并且可以独立开发、测试、部署…...

数据结构之算法的时间复杂度
1.时间复杂度的定义 在计算机科学中,算法的时间复杂度是一个函数,它定量描述了算法的运行时间。一个算法所花费的时间与其中语句的执行次数成正比列,算法中的基本操作的执行次数,为算法的时间复杂度 例1: 计算Func1…...

unity中物体被激活自动执行挂载代码
在Unity中,如果希望当物体被激活时自动执行特定的函数,可以利用 MonoBehaviour 的生命周期函数 OnEnable()。这个方法会在对象被激活时调用,可以用来执行初始化或者处理其他逻辑。以下是如何在脚本中使用 OnEnable() 方法: using UnityEngine;public class ActivateFuncti…...

Pandas数据可视化详解:大案例解析(第27天)
系列文章目录 Pandas数据可视化解决不显示中文和负号问题matplotlib数据可视化seaborn数据可视化pyecharts数据可视化优衣库数据分析案例 文章目录 系列文章目录前言1. Pandas数据可视化1.1 案例解析:代码实现 2. 解决不显示中文和负号问题3. matplotlib数据可视化…...

Redis基础教程(七):redis列表(List)
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝Ὁ…...

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【生成密钥(C/C++)】
生成密钥(C/C) 以生成ECC密钥为例,生成随机密钥。具体的场景介绍及支持的算法规格。 注意: 密钥别名中禁止包含个人数据等敏感信息。 开发前请熟悉鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复…...

ssm“落雪”动漫网站-计算机毕业设计源码81664
目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据新增流程 3.2.2 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…...

【面试题】Reactor模型
Reactor模型 定义 Reactor模型是一种事件驱动的设计模式,用于处理服务请求。它通过将事件处理逻辑与事件分发机制解耦,实现高性能、可扩展的并发处理。Reactor模型适用于高并发、事件驱动的程序设计,如网络服务器等。 特点 事件驱动&#…...

RedHat9 | kickstart无人值守批量安装
一、知识补充 kickstart Kickstart是一种用于Linux系统安装的自动化工具,它通过一个名为ks.cfg的配置文件来定义Linux安装过程中的各种参数和设置。 kickstart的工作原理 Kickstart的工作原理是通过记录典型的安装过程中所需人工干预填写的各种参数,…...

k8s-第五节-StatefulSet
StatefulSet StatefulSet 是用来管理有状态的应用,例如数据库。 前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。 而像**数据库、Redis **这类…...

ai机器狗
ai机器狗的代码很早就开源了,相当于核心,最难东西美国人公开了,开源了,如果有钱,有足够资源的,造出东西有可能比公开这些核心代码的公司或者组织还好。没有技术含量,技术含量别人都解决了&#…...

数据库关键字执行顺序
在 SQL 中,关键字的执行顺序通常如下: FROM:确定要查询的表或数据源,并执行表之间的连接操作(如 INNER JOIN、LEFT JOIN 等)。FROM 子句执行顺序为从后往前、从右到左。ON:应用连接条件…...

Linux 永久挂载磁盘
文章目录 前言一、使用步骤1.命令 总结 前言 一、使用步骤 1.命令 第一步:创建挂载点 sudo mkdir /hhkj 第二步:磁盘挂载到挂载点(lsblk、lvdisplay) sudo mount /dev/sdb2 /hhkj 或者 sudo mount /dev/centos/home /hhkj 第三…...