从零全面认识 多线程

目录

 1.基本概念

2.创建线程方式

2.1直接建立线程

2.2实现Runnable接口

3.3实现Callable接口

3.4 了解Future接口

Future模式主要角色及其作用

3.5实例化FutureTask类

3.实现线程安全

3.1定义

3.2不安全原因

3.3解决方案

3.4volatile与synchronized区别

3.5Lock与sychronized区别

4.极端情况——线程死锁

4.1定义

4.2解决措施

5.线程池的掌握

5.1核心参数

5.2生命周期

5.3处理流程

5.4Handler拒绝策略

5.5常见线程池

5.6线程池的使用


 1.基本概念

线程状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、

                  等待(Waiting)、超时等待(Timed Waiting)、终止(Terminated)

锁(同步监视器):分为悲观锁和乐观锁,常见的有偏向锁、轻量级锁、重量级锁

                                CAS(Compare And Swap)是一种乐观锁的实现方式,通过比较并

                                交换来实现并发控制

2.创建线程方式

Runnable接口、Callable接口、Future接口、FutureTask类

2.1直接建立线程

        创建Thread子类,按需求重写run()方法 【run代表此线程执行时会做的事】

        这里的属性若为 多线程共享属性,加static修饰

2.2实现Runnable接口

 这里的 多线程共享属性 可以是非静态的,因为多线程共用此接口

3.3实现Callable接口

(1)实现接口Callable,重写call()回调方法,会返回一个值,值类型由Callable泛型决定

实例化上述类,利用FutureTask(Callable)构造器实例化类

3.4 了解Future接口

异步调用的多线程开发模式之一(异步:当我们需要调用一个函数方法时,并不急着要结果。让被调者立即返回,让它在后台慢慢处理这个请求;此时则可以先处理一些其他任务

Future模式主要角色及其作用

Main->调用Client发送请求

Data->返回数据的接口

Client->返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData

FutureData->虚拟数据,伪造数据立即返回,最终装配上RealData

RealData->真实数据,构造缓慢

3.5实例化FutureTask类

FutureTask用于异步获取执行结果或取消执行任务

通过传入Runnable或者Callable的任务给FutureTask,

直接调用其run方法或者放入线程池执行,

最后在外部通过FutureTask的get方法异步获取执行结果(适合耗时操作)

3.实现线程安全

3.1定义

多线程环境下,对共享资源的访问不会导致数据出错。

因此和单线程执行相同的操作,结果相同

3.2不安全原因

1. 线程是抢占式的执行,线程间的调度充满了随机性
2. 多个线程对同一个变量进行修改操作
3. 对变量的操作不是原子性的
4. 内存可见性导致的线程安全问题
5. 指令重排序也会影响线程安全

3.3解决方案

使用同步机制(如synchronized、Lock)、

使用线程安全的数据结构(如ConcurrentHashMap)

synchronized:Java关键字,属于隐式锁,可以修饰方法或代码块

Lock:JAVA接口,显式锁

原理上都是通过对共享资源加锁来实现同步。

3.4volatile与synchronized区别

volatile轻量级的锁,保证变量的可见性和有序性,但仅仅保证单个变量的原子性

可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入,解决多核CPU缓存可见性问题

有序性:采用内存屏障来实现的,就是在编译器生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序

原子性:对单个volatile变量的读写具有原子性,对“volatile变量++”这种复合操作则不具有原子性,

而synchronized既保证可见性又保证原子性

volatile适用于单个变量的读写操作,而synchronized适用于复合操作或临界区。

3.5Lock与sychronized区别

使用方式: 1、Lock接口是显式锁,即我们需要调用其内部定义的方法显式地加锁和解锁,更加灵活,Lock对象创建Condition对象来实现线程通信

                   2、synchronized关键字是隐式锁,无需显式地获取和释放锁,使用方便

 功能特性:Lock弥补了synchronized的不足,它新增了特性:1、可中断地获取锁,2、 非阻塞地获取锁,3、可超时地获取锁

实现机制:AQS是队列同步器,是用来构建锁的基础框架,Lock实现类都是基于AQS实现的

                  synchronized的底层是采用Java对象头来存储锁信息的,对象头包含三部分,分别是Mark Word、Class Metadata Address、Array length。

4.极端情况——线程死锁

4.1定义

多个线程相互等待对方释放资源,导致无法继续执行

4.2解决措施

  1. 避免嵌套锁、

  2. 按固定的顺序获取锁、

  3. 设置超时时间、

  4. 使用Lock对象代替synchronized关键字。

5.线程池的掌握

5.1核心参数

核心线程数(corePoolSize):依据任务的处理时间和每秒产生的任务数量来确定

最大线程数(maximumPoolSize):参照核心线程数和系统每秒产生的最大任务数决定

线程空闲时间(keepAliveTime):用户自设置合理时间间隔

任务队列(workQueue):一定的顺序或优先级来执行任务

拒绝策略(handler):线程池已经关闭或达到饱和(最大线程和队列都已满)状态时,新提交的

                                任务将会被拒绝。

5.2生命周期

线程池的生命周期包含5个状态:

  • RUNNING:线程池正在运行,接受新任务并执行。
  • SHUTDOWN:任务队列不清空,线程池不再接受新任务,等待执行的任务继续执行完毕。
  • STOP:清空任务队列,不等待执行的任务,尝试终止正在执行的任务。
  • TIDYING:当线程池及任务队列为空时进入该状态,线程池会执行钩子函数(待实现)。
  • TERMINATED:线程池终止状态,所有任务执行完毕,线程池关闭。

注意:

在线程池的生命周期中,它的状态是不可逆

5.3处理流程

向线程池提交一个任务之后,线程池按照如下步骤处理这个任务

注意:

1、新建的线程处理完当前任务后,变为空闲线程,继续处理等待队列中的任务。

2、如果线程的空闲时间达到了keepAliveTime,则线程池会销毁一部分线程,将线程数量收缩至corePoolSize。

5.4Handler拒绝策略

Hanlder通常处理消息,但线程池中帮助任务异步执行,发送消息并执行UI更新等操作

拒绝策略分别对应着RejectedExecutionHandler接口的4个实现类,

1、让调用者自己执行任务

2、直接抛出异常

3、丢弃任务不做任何处理

4、删除队列中最老的任务并把当前任务加入队列

5.5常见线程池

FixedThreadPool、CachedThreadPool、ScheduledThreadPool

5.6线程池的使用

1:利用Executors工厂类的静态方法,创建线程池对象;
2:编写Runnable或Callable实现类的实例对象;
3:利用ExecutorService的submit方法或ScheduledExecutorService的schedule方法提交并执行线程任务
4:如果有执行结果,则处理异步执行结果(Future)
5:调用shutdown()方法,关闭线程池

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

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

相关文章

创建线程池的例子

public class ExecutorTest {public static void main(String[] args) {//创建线程池的5种方式: // Executors.newFixedThreadPool();//创建固定线程数的线程池 // Executors.newSingleThreadExecutor();//创建单线程的线程池 // Executors.ne…

Geeker-Admin:基于Vue3.4、TypeScript、Vite5、Pinia和Element-Plus的开源后台管理框架

Geeker-Admin:基于Vue3.4、TypeScript、Vite5、Pinia和Element-Plus的开源后台管理框架 一、引言 随着技术的不断发展,前端开发领域也在不断演变。为了满足现代应用程序的需求,开发人员需要使用最新、最强大的工具和技术。Geeker-Admin正是…

activiti初次学习

源代码地址:https://gitee.com/ZSXYX/activiti.git​ 1、安装插件 首先安装下图所示activiti,不确定是哪个插件有用的,有时间可排除下 在resources下创建一个文件夹:processes,右键,新建 生成: 选中act.bpmn20.xm…

基于ICEEMDAN-SVD的信号去噪算法

一、代码原理 ICEEMDAN-SVD算法是一种结合了Improved Complete Ensemble Empirical Mode Decomposition with Adaptive Noise (ICEEMDAN) 和奇异值分解 (SVD) 的信号去噪方法。这种算法结合了两种先进的信号处理技术,旨在提高信号去噪的效果。以下是该算法的基本原…

第24次修改了可删除可持久保存的前端html备忘录:文本编辑框不再隐藏,又增加了哔哩哔哩搜索和必应搜索

第24次修改了可删除可持久保存的前端html备忘录:文本编辑框不再隐藏&#xff0c;又增加了哔哩哔哩搜索和必应搜索. <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"…

shell-将密码输入错误超过4次的IP地址通过firewalld防火墙阻止访问

应用场景&#xff1a;防止恶意IP尝试ssh登录 脚本说明&#xff1a;将密码输入错误超过四次得ip地址通过iptable防火墙访问。 分析&#xff1a; 首先&#xff0c;需要知道ssh远程访问记录在哪一个文件中 /var/log/secure 其次&#xff0c;模拟远程访问输错密码&#xff0c;查…

Vulnhub靶机 DC-1渗透详细过程

Vulnhub靶机:DC-1渗透详细过程 目录 Vulnhub靶机:DC-1渗透详细过程一、将靶机导入到虚拟机当中二、攻击方式主机发现端口扫描web渗透利用msf反弹shell数据库信息web管理员密码提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://www.vulnhub.com/entry/dc-1-1,29…

【域适应】基于域分离网络的MNIST数据10分类典型方法实现

关于 大规模数据收集和注释的成本通常使得将机器学习算法应用于新任务或数据集变得异常昂贵。规避这一成本的一种方法是在合成数据上训练模型&#xff0c;其中自动提供注释。尽管它们很有吸引力&#xff0c;但此类模型通常无法从合成图像推广到真实图像&#xff0c;因此需要域…

在Mac上更好的运行Windows,推荐这几款Mac虚拟机 mac运行windows虚拟机性能

想要在Mac OS上更好的运行Windows系统吗&#xff1f;推荐你使用mac虚拟机。虚拟机通过生成现有操作系统的全新虚拟镜像&#xff0c;它具有真实windows系统完全一样的功能&#xff0c;进入虚拟系统后&#xff0c;所有操作都是在这个全新的独立的虚拟系统里面进行&#xff0c;可以…

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能&#xff0c;其实就两大步&#xff0c;1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

深入理解Cortex-M7 SVC和PendSV

1前言 1.1 PendSV 在ARM V7上&#xff0c;PendSV用来作为RTOS调度器的御用通道&#xff0c;上下文切换&#xff0c;任务调度都是在其ISR中实现的。所谓pend&#xff0c;字面意思即有悬起等待的意思&#xff0c;ARM官方也明确说明&#xff0c;PendSV应该在其他异常处理完毕后执…

python的算术运算符

python常用算术运算符代码如下&#xff1a; #算术运算符操作 x 10 y 20 z 30 #加法运算 a x y print("a的值为&#xff1a;", a) #减法运算 a x - y print("a的值为&#xff1a;", a) #乘法运算 a x*y print("a的值为&#xff1a;", a) …

计算机网络——ARP协议

前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 这篇博客是在B站掌芝士zzs这个UP主的视频的总结&#xff0c;讲的非常好。 可以先去看一篇视频&#xff0c;再来参考这篇笔记&#xff08;或者说直接偷走&#xff09;。 …

OpenCV4.9​​​​基本阈值操作

目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 cv&#xff1a;&#xff1a;threshold 执行基本阈值操作 理论依据 注意 下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书 阈值&#xff1f; 最简单的分割方法应用示例&#xff1a;分…

步骤大全:网站建设3个基本流程详解

一.领取一个免费域名和SSL证书&#xff0c;和CDN 1.打开网站链接&#xff1a;https://www.rainyun.com/z22_ 2.在网站主页上&#xff0c;您会看到一个"登陆/注册"的选项。 3.点击"登陆/注册"&#xff0c;然后选择"微信登录"选项。 4.使用您的…

Claude3和GPT4哪个强?

在短短两个月内&#xff0c;全球最强人工智能的桂冠再次易主。此前&#xff0c;Claude3 Opus以其卓越的表现超越了GPT-4&#xff0c;吸引了无数用户抛弃GPT&#xff0c;转而拥抱Claude3。然而&#xff0c;OpenAI近日强势回归&#xff0c;用实力证明了GPT依然是人工智能领域的霸…

Jmeter杂记:测试计划参数详解

测试计划各参数详解 1&#xff0c;用户自定义变量&#xff0c;是全局变量&#xff0c;供所有线程组使用&#xff0c;可用配置元件&#xff1a;用户自定义变量替代 2&#xff0c;连续的运行线程组&#xff0c;默认不勾选&#xff0c;则随机的运行多个线程组中的取样器&#xff…

图机器学习NetworkX代码实战-创建图和可视化

完整代码见资源&#xff0c;下面列举了其中的几个图 安装networkX及相应工具包 pip install numpy pandas matplotlib tqdm networkx 当安装完成后&#xff0c;输入如下代码验证版本及是否安装成功 import networkx as nxnx.__version__ import matplotlib.pyplot as plt …

国内ai人工智能软件大全

很多人一直在寻找一个稳定且可靠的全球AI大模型测试平台&#xff0c;希望它不仅真实可信&#xff0c;而且能提供稳定、快速的服务&#xff0c;不会频繁出现故障或响应缓慢。迄今为止&#xff0c;我已经尝试了国内外至少10个不同的服务站点。不幸的是&#xff0c;这些站点总是存…

Linux 文件页反向映射

0. 引言 操作系统中与匿名页相对的是文件页&#xff0c;文件页的反向映射对比匿名页的反向映射更为简单。如果还不清楚匿名页反向映射逻辑的&#xff0c;请移步 匿名页反向映射 1. 文件页反向映射数据结构 struct file&#xff1a; 用户进程每open()一次文件&#xff0c;则会生…