Java并发编程 JUC常见问题

创建多线程的方式:

run方法和start方法:
  • 调用run方法和调用普通方法一样,是现有线程去同步串行地调用,可以调用多次
  • 调用start方法是异步开启一个新线程,只能调用一次

线程的六个状态

wait()和slepp()的异同

重点:
  • wait方法要与synchronized锁配合使用,sleep方法不需要
  • wait(Long time)方法执行之后主动释放锁,给其他线程执行。sleep不会主动释放,只有sleep时间过了之后才释放

synchronized关键字原理

AQS原理

ReentrantLock(基于AQS实现)

死锁排查

jps命令:输出JVM的进程信息

jstack命令:查看java进程内线程的堆栈信息

ConcurrentHashMap

JDK 8 之前

一个 ConcurrentHashMap 里包含一个 Segment 数组,Segment 的个数一旦初始化就不能改变Segment 数组的大小默认是 16,也就是说默认可以同时支持 16 个线程并发写。

Segment 的结构和 HashMap 类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个 HashEntry 数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 的锁。也就是说,对同一 Segment 的并发写入会被阻塞,不同 Segment 的写入是可以并发执行的。


JDK 8 之后

ConcurrentHashMap 取消了 Segment 分段锁,采用 Node + CAS + synchronized 来保证并发安全。数据结构跟 HashMap 1.8 的结构类似,数组+链表/红黑二叉树。Java 8 在链表长度超过一定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红黑树(寻址时间复杂度为 O(log(N)))。

Java 8 中,锁粒度更细,synchronized 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发,就不会影响其他 Node 的读写,效率大幅提升。

添加新节点使用CAS判断,如果哈希冲突了,用synchronized锁住链表/红黑树的首节点。

相对segment,锁的粒度更细,性能也就更好

volatile关键字作用

线程池

线程池7大参数

执行流程、拒绝策略

  • ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。
  • ThreadPoolExecutor.CallerRunsPolicy:调用执行者自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。
  • ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。
  • ThreadPoolExecutor.DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值