每天一学(2)

目录

1、线程池是如何知道线程任务是否完成

2、阻塞队列的有界和无界

3、ConcurrentHashMap底层实现原理

5、CAS机制

[6、wait 和 notify 为什么要放在 synchronized](#6、wait 和 notify 为什么要放在 synchronized)


1、线程池是如何知道线程任务是否完成

线程池内部

当把任务丢给线程池去执行,调度工作线程, 通过同步调用执行 run () 方法,正常结束, 等待方法返回 直到结束,

线程外部:

线程池提供了isInterrupted () 方法 判断线程池的运行状态 结果是 意味着任务执行完成 submit 方法 通过 future.get() 方法 正常返回 意味着结束 没有返回则一直执行

引入CountDownLatch 计数器 进行倒计时 有两个方法 :

1、await()阻塞线程

2、countDown() 进行倒计时,一旦倒计时归零,所有阻塞在await()方法的线程都会被释放

2、阻塞队列的有界和无界

阻塞队列是特殊的队列,1、当队列为空,获取队列中元素的消费者线程,它会被阻塞,同时唤醒生产者线程,2、当队列中元素满了,向队列中添加元素的生产者线程,它会被阻塞,同时唤醒消费者线程。

有界队列: 阻塞队列中容纳的个数是有限的,比如去实例化一个ArrayBlocking List,可以在构造方法传一个整形的数字,表示基于数组的阻塞队列中,能够容纳的元素个数,称为

无界队列:就是没有设置固定大小的队列,并不是没有任何限制,而是元素存储量很大。无界队列存在比较大的潜在风险,并发量较大的情况下,线程池中几乎可以无限制的添加任务,容易导致内存溢出。

3、 ConcurrentHashMap底层实现原理

整体架构:

jdk1.8 由数组+红黑树+单向链表构成,默认初始化长度16的数组,由于核心仍是hashmap ,必然会存在hash冲突, 所有ConcurrentHashMap采用链式寻址的方式

解决hash 冲突:当hash冲突比较多的时候,会造成链表长度问题, jdk 1.8 引入红黑树,当数组长度大于64,并且链表长度大于8,单向链表会转化为红黑树。当链表长度小于8,红黑树就会退化为单项链表。

基本功能:

在hashmap基础上提供了并发安全的实现,通过对于node节点去加锁,来保证数据更新的安全性。性能方面优化:

jdk1.8、ConcurrentHashMap 的锁粒度是数组中某一个节点,

jdk1.7 、锁定的是segment 锁的范围要更大,性能上会更低,

引入红黑树,降低数据查询的时间复杂度

当数组长度不够的时候,对数组进行扩容, 引入了多线程并发扩容(多个线程对原始数组进行分片),每个线程负责对一个分片的迁移。

4、死锁发生的原因 怎么避免

死锁:多个锁去竞争同一个资源 造成相互等待,如果没有外部干预、将无法往下执行

导致死锁的条件:

  1. 互斥条件 共享资源x和y 只能被一个线程占用
  2. 请求和保持条件 A线程已经取得共享资源x 在等待共享资源y的时候,不释放x
  3. 其他线程不能强行抢占线程A 占有的资源
  4. 循环等待:线程A 等待B占有的资源 B等待A占有的资源

解决死锁:

通过人工干预来解决, 重启服务、或者kill 掉线程

破坏其中任意一种 (互斥条件没办法破话) 互斥条件是互斥锁的基本约束

5、CAS机制

CAS是java中unsafe类里面的一个方法,全称:Compare and Swap比较并交换

主要功能: 保证在多线程环境下,对于共享变量修改的一个原子性

例子: 有一个成员变量state默认值为0 ,定义了一个方法,逻辑为,先判断state是否为0,如果为0 就修改为1,在单线程没有任何问题,多线程下会存在原子性问题。 这是是一个 read -write 操作, 一般解决会在方法 加 synchronized同步锁来解决,但是加锁 会带来性能上的损耗, 所以可以采用CAS机制进行优化。

6、wait 和 notify 为什么要放在 synchronized

wait 和notify 为了实现多个线程之间的协调, 阻塞/被唤醒 。他俩必然成对出现,

要实现多线程之间的通信,除了管道流,只能通过共享变量的方法来实现,A线程修改共享变量s ,线程B 获得修改之后共享变量s的值

但是多线程本身具有并行执行的特征,同一时刻多个线程可以同步执行,线程B 在访问共享变量之前,必须要知道线程A已经修改过共享变量S, 修改完同时唤醒等待状态下的线程, synchronized 可以实现互斥条件,实现条件等待条件唤醒,为了避免wait /notify 错误使用,强制放入同步代码块。

相关推荐
景天科技苑2 天前
【Rust线程池】如何构建Rust线程池、Rayon线程池用法详细解析
开发语言·后端·rust·线程池·rayon·rust线程池·rayon线程池
码观天工13 天前
从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
redis·线程池·线程饥饿
玩代码16 天前
Java线程池原理概述
java·开发语言·线程池
佛祖让我来巡山19 天前
【线程池饱和策略】线程池饱和策略及自定义方法
线程池·java线程池·线程池饱和策略
百锦再1 个月前
.NET多线程任务实现的几种方法及线程等待全面分析
android·.net·线程·线程池·并发·thread·task
A22741 个月前
自定义线程池 4.0
java·线程池
阿维的博客日记1 个月前
说一下Java里面线程池的拒绝策略
java·线程池·拒绝策略
寒山李白2 个月前
Java中高并发线程池的相关面试题详解
java·开发语言·面试·高并发·线程池·多线程
Maỿbe2 个月前
java中的CAS机制
java·线程·进程·cas
LUCIAZZZ2 个月前
HikariCP数据库连接池原理解析
java·jvm·数据库·spring·springboot·线程池·连接池