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

(原创)学习资料-多线程相关

资料来源:黑马java视频

线程的几种状态:

参考博客

参考视频

一共六种

NEW:初始化态

线程被创建

RUNNABLE:运行态

又分为就绪状态和运行中两个状态

BLOCKED:阻塞态

线程阻塞于锁,在外面等待的时候称为阻塞态
有且仅有synchronized才能进入这个状态
如果是Lock的话,进入的是等待或者等待超时

WAITING:等待状态

拿到锁后发现不符合运行条件,需要暂停执行(比如调用wait让出锁,或者condition.await())
让出cpu资源 供其他线程执行

TIMED_WAITING:超时等待

等待固定时间,在时间到达后自行返回
相比于等待状态需要其他条件唤醒,这个状态可以做到根据时间自行唤醒

TERMINATED:结束态

线程结束
线程状态可以看下图:

解决多线程安全问题的几种方式

1:同步代码块

synchronized (对象:锁旗标){
//需要被同步的代码
}

2:同步函数

Synchronized+void+方法名
注意:同步函数的锁旗标是他本身的对象引用,也就是this
静态同步函数的锁旗标是该方法所在类的字节码文件对象,也就是类名.class

锁的弊端:多线程时需要判断锁,较为消耗资源

3:Lock 和 Condition

Java1.5以后加入了Lock 和 Condition
更加显性的给线程进行同步控制
使用方法如下:

Locklock=newReentrantLock();lock.lock();try{//写你的同步代码}catch(Exceptione){}finally{lock.unlock();}

Condition主要是用来对线程进行睡眠和唤醒的操作
替代wait,notify,notifyAll
lock.newCondition()方法可以得到一个Condition对象
他有几个方法:
condition.await(); 线程等待
condition.signal(); 线程唤醒
condition.signalAll(); 唤醒这个锁的所有线程
另外还可以多次调用newCondition返回多个Condition对象
每个对象调用自己的await和signal进行等待和唤醒操作
这样可以做到对指定的Condition对象进行等待和唤醒操作
conditionA调用await,只能用conditionA的signal来进行唤醒

sleep和wait

Sleep(time)

让线程进入睡眠状态,传入一个时间,时间到了,线程重新唤醒
Sleep 不会释放锁资源

wait,notify,notifyAll方法介绍:

他们都使用在同步函数或者同步代码块中,功能是对持有锁的线程进行等待或者唤醒操作
因为只有同步才具有锁。所以要使用在同步中

只有同一个锁上的被等待线程,可以被同一个锁上 notify 唤醒.
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁旗标。
因为锁旗标可以是任意对象,所以可以被任意对象调用的方法定义 object类中.
wait会释放锁资源

死锁

两个线程A和B在同步的时候互相持有对方的锁
A需要B的锁才能继续执行
B需要A的锁才能继续执行
这样就导致了死锁
一般是同步嵌套同步容易导致死锁
开发时需要注意避免死锁
避免死锁的方式:
可以利用好Lock.tryLock+sleep()的方法
这个方法是尝试拿锁
拿锁成功返回true
拿锁失败返回false
这样就可以成功避免死锁
sleep主要是为了放开资源
避免单个线程重复拿到锁
如下面两个图

停止线程的方法

线程只有执行完Run方法才会结束
不推荐调用stop的方法去停止线程
因为容易导致死锁等问题
虽然不能停止
但是java提供了中断线程的方法
interrupt():设置当前线程状态为中断状态
配合另外两个方法一起使用
isInterrupted()判断线程是否中断
这样就可以根据这个状态来做实际的逻辑
interrupted()判断线程是否中断,判断完之后
会将线程的中断状态清除
就是如果线程被interrupt()方法设置线程中断了
第一次调用,会返回true,并且清除掉中断状态
第二次调用
除非再次调用interrupt()方法设置线程中断
不然就会返回false。

Join方法

线程A调用这个join方法,会抢夺当前线程B的执行权
A线程执行完了之后,才会把执行权重新还给B
比如主线程中创建了一个新的子线程A,然后A.join
主线程就会停止往下走
直到A线程执行完,主线程才会继续往下走
这个方法可以用来临时加入一个线程执行
Join不会释放锁资源

yield方法

线程调用自身的这个方法,代表让出执行权
进入到就绪状态,重新抢夺cpu资源
yield也不会释放锁资源

线程的可见性,原子性,有序性

可见性:

是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
Java线程里有一个主内存和工作内存之分,一个子线程,会把主内存的变量的值缓存在工作内存之中。故而不同的线程,对于同一个变量都有一个自己缓存的值。
如果要保证可见性,可以加volatile关键字或者synchronized同步,以及final

原子性:

严格的原子性的操作,其他线程获取操作的变量时,只能获取操作前的变量值和操作后的变量值,不能获取到操作过程中的中间值,在操作过程中其他操作需要获取变量值,需要进入阻塞状态等待操作结束。如果要保证原子性,可以加synchronized或者锁,保证同一时间只有一个线程操作变量

有序性:

在并发时,程序的执行可能会出现乱序。给人的直观感觉就是:写在前面的代码,会在后面执行。有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。
有序性可以看这个视频:
https://www.bilibili.com/video/BV1XT4y1M7E9?p=6

volatile关键字的作用

1、保证可见性;
2、防止指令重排(抑制重排序);
3、但是不保证原子性;
volatile的作用就是这样,被volatile修饰的变量,保证了每次读取到的都是最新的那个值。线程安全围绕的是可见性和原子性这两个特性展开的,volatile解决的是变量在多个线程之间的可见性,但是无法保证原子性。

多提一句,synchronized除了保障了原子性外,其实也保障了可见性。因为synchronized无论是同步的方法还是同步的代码块,都会先把主内存的数据拷贝到工作内存中,同步代码块结束,会把工作内存中的数据更新到主内存中,这样主内存中的数据一定是最新的。

synchronized: 具有原子性,有序性和可见性
volatile:具有有序性和可见性

线程池

四种常见的线程池:

CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。

SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。

SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。如果线程因为异常而停止,会自动新建一个线程补充

FixedThreadPool:一个核心线程数跟最大线程数相同的线程池,线程池数量大小不变,如果有任务放入队列,等待空闲线程。

工作原理

1、线程在有任务的时候会创建核心的线程数corePoolSize
2、当线程满了(有任务但是线程被使用完)不会立即扩容,而是放到阻塞队列中,当阻塞队列满了之后才会继续创建线程。
3、如果队列满了,线程数达到最大线程数则会执行拒绝策略。
4、当线程数大于核心线程数事,超过KeepAliveTime(闲置时间),线程会被回收,最终会保持corePoolSize个线程。

七个核心参数

corePoolSize: 线程池核心线程个数

workQueue:用于保存等待执行任务的阻塞队列

maximunPoolSize: 线程池最大线程数量

ThreadFactory: 创建线程的工厂

RejectedExecutionHandler: 队列满,并且线程达到最大线程数量的时候,对新任务的处理策略

keeyAliveTime: 空闲线程存活时间

TimeUnit: 存活时间单位

拒绝策略

1、AbortPolicy(被拒绝了抛出异常)

2、CallerRunsPolicy(使用调用者所在线程执行,就是哪里来的回哪里去)

3、DiscardOldestPolicy(尝试去竞争第一个,失败了也不抛异常)

4、DiscardPolicy(默默丢弃、不抛异常)

拒绝策略执行则么办?

1、另外创建一个队列,当拒绝策略执行将任务放入队列。

通过定时任务去每隔一秒去查看线程池队列中是否有任务,没有则添加进去。

缺点: 任务会丢失,线程优雅关闭是指正常情况队列执行晚。会关闭。如果用这种方法创建则会丢失任务。

2、如果 是特别重要的话就 放入DB去持久化,给任务加个状态,通过状态来判断任务的执行情况。

3、其他情况要根据场景考虑 比如又些任务过期淘汰

判断线程池执行完任务

https://blog.csdn.net/u013310119/article/details/117926703

http://www.jsqmd.com/news/502484/

相关文章:

  • AI实践(8)Skills技能
  • 专业瓷砖修复公司推荐 行业优质服务商盘点 - 资讯焦点
  • 万象熔炉·丹青幻境Java集成实战:SpringBoot后端智能图像生成服务
  • 欧姆龙CP1H标准程序,一共控制五个伺本体四个+一个轴扩展包 含轴点动,回零,相对与绝对定位...
  • 零门槛Windows和Office激活完整指南:轻松搞定全版本系统激活
  • 深度学习实战:从零构建神经网络模型
  • 【会话:Cookie与Session】Cookie与Session的区别(附对比表)
  • 2026年沙子烘干机厂家推荐:深度解析行业郑州市永大机械! - 深度智识库
  • 突破DAPO算法瓶颈:动态批次生成的优化实践与性能提升
  • DLT:dlt-daemon示例解析2
  • Linux使用信号量sem_timedwait当作定时器
  • 编程语言扩展与驱动交互 - C扩展
  • 【JUC 一】线程 进程 synchronized Lock锁 生产者 消费者 8锁 线程安全集合类...
  • 企业上云如何避坑?2026年主流云主机深度对比与决策指南 - 资讯焦点
  • 深入解析PE内存注入技术:从文件到shellcode的转换机制
  • Python爬虫进阶:自动化采集语音训练数据实战
  • 国内云平台选购指南:主流服务对比与价格解析 - 资讯焦点
  • macOS鼠标滚动优化解决方案:提升效率的平滑滚动技术实现
  • MATLAB R2023b安装包下载及安装步骤说明
  • Phi-3-Mini-128K实战:利用卷积神经网络原理优化模型提示策略
  • 2026南京定制假发优质公司推荐榜 - 资讯焦点
  • 郑州叮叮智能荣登2026行业十大品牌,新晋实力派彰显领军风范 - 深度智识库
  • 2026年青岛留学中介哪家口碑好:五家优选深度解析 - 科技焦点
  • webpack的使用步骤及插件使用方法
  • 武汉医美哪家好?推荐几家靠谱的武汉医疗美容和机构 - 资讯焦点
  • HPatches数据集实战:从特征点检测到匹配精度的全链路评估
  • ROS+Prescan+Carsim联调实战:手把手搭建自动驾驶硬件在环测试平台(附避坑指南)
  • 选对名师少走弯路,药学主任药师考试高分名师推荐 - 医考机构品牌测评专家
  • EasyAnimateV5-7b-zh-InP与Typora结合:Markdown文档转视频教程
  • 别再跟风“代装”了!2026年OpenClaw“养虾”避坑实战指南