欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

JUC

程序员文章站 2022-06-15 23:36:03
请滑走,自用,无营养警告⚠目录2.CAS3.ArrayList不安全5.阻塞队列6.Synchronized和Lock的区别7.线程池 ThreadPoolExecutor线程池7大参数拒绝策略2.CAS从引出下面的问题AtomicInteger->CAS ->调用UnSafe类中的CAS方法直接操作内存 ->自旋: CAS思想 -> ABAatomicInteger.getAndIncrement(){return unsafe.ge...

请滑走,自用,无营养警告⚠

目录

2.CAS

3.ArrayList不安全

5.阻塞队列

6.Synchronized和Lock的区别

7.线程池 ThreadPoolExecutor

线程池7大参数

拒绝策略


2.CAS

从引出下面的问题

AtomicInteger->CAS ->调用UnSafe类中的CAS方法直接操作内存 ->自旋: CAS思想 -> ABA

atomicInteger.getAndIncrement(){return unsafe.getAndInt(this,valueoffset,1)

AtomicInteger的value是volatile修饰的

缺:循环时间长,开销大/只能保证一个共享变量的原子操作/ABA

ABA解决:1.AtomicStampedReference修改版本号,时间戳 2.LongAdder

 

3.ArrayList不安全

初始10 扩容1.5 add没加syn

Arrays.copyOf(elementData, netCapacity)
int newCapacity = oldCapacity + (oldCapacity >> 1);

ConcurrentModificationException 并发修改的异常

解决1vector 加锁了,并发性小 2. Collections.synchronizedList(new ArrayList<>());

3.CopyOnWriteArrayList:写时复制,读写分离 add里面加可重入锁

 

HashSet线程不安全:CopyOnWriteArraySet

HashMap 1 使用Collections.synchronizedMap 2使用 ConcurrentHashMap

 

HashTable

  • 底层数组+链表实现,key value都不能为null,线程安全,修改数据时锁住整个HashTable,效率低
  • 初始size为11,扩容:newsize = olesize*2+1
  • 计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

ConcurrentHashMap

  • 分段的数组+链表实现,线程安全
  • 整个Map分为N个Segment (读操作不加锁)
  • 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

5.阻塞队列

BlockingQueue 阻塞队列 接口 什么时候阻塞(即挂起),唤醒不需要程序员控制细节

七个实现类

  • ArrayBlockQueue:数组有界阻塞队列 LinkedBlockingQueue:链表假有界

  • PriorityBlockQueue:支持优先级排序的*

  • DelayQueue:使用优先级队列实现的延迟*阻塞队列

  • SynchronousQueue:生产一个,消费一个,不存储元素,不消费不生产

  • LinkedTransferQueue:*阻塞队列LinkedBlockingDeque:双向阻塞队列

【核心方法】

   
1 抛出异常:::队列满时add , 队列空时remove,抛异常
2 特殊值:::offer,成功true,失败false poll():成功返回出队列元素,队列没有就返回空
3 一直阻塞:::队列满,put 阻塞生产线直到可以put, 队列空时,take同理
4 超时退出:::队列满时,阻塞生产者线程一定时间 offer(e,time,unit) poll(time,unit)

6.Synchronized和Lock的区别

synchronized属于JVM层面,ReentrantLock 是 JDK (juc)实现的。

monitorenter 只能在同步块 或 方法中 才能调用 wait/ notify

synchronized:不需要用户去手动释放锁,不用担心死锁

synchronized不可中断 ReentrantLock:可设置超时方法, 也可lockInterrupible()

非公平

ReentrantLock:精确唤醒

7.线程池 ThreadPoolExecutor

提交任务请求

  1. 正在运行线程小于corePoolSize,马上创建线程运行任务,大于或等于corePoolSize,任务放入队列

  2. 队列满了,创建非核心线程

  3. 大于maximumPoolSize,拒绝策略

  1. 当一个线程完成任务时,从队列中取下一个

  2. 当一个线程无事可做操作一定的时间,停掉线程,直到收缩到corePoolSize的大小

线程池7大参数

  • corePoolSize:核心线程数,线程池中的常驻核心线程数

    • 有请求任务来之后,就会安排池中的线程去执行请求任务,达到corePoolSize后,放到缓存队列中

  • maximumPoolSize:线程池能够容纳同时执行的最大线程数

  • keepAliveTime:多余的空闲线程存活时间

  • unit:时间单位

  • workQueue:任务队列,被提交的但未被执行的任务

  • threadFactory:

  • handler:大于最大线程数

拒绝策略

  • AbortPolicy:抛异常

  • DiscardPolicy:直接丢弃任务,不予处理不抛异常

  • CallerRunsPolicy:不抛弃任务,不抛异常,而是将任务回退到调用者

  • DiscardOldestPolicy:抛弃队列中等待最久的任务,加入当前的

  •  

线程池创建的方法有:固定数的,单一的,可变的,那么在实际开发中,应该使用哪个?

都不用 运行的请求队列长度为:Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM

ExecutorService executorService = new ThreadPoolExecutor(参数)

executorService.execute(() -> {}) //for循环里

 

如何配置 corePoolSize 和 maximumPoolSize

  • CPU密集型 任务需要大量的运算,而没有阻塞,CPU一直全速运行,CPU核数 + 1个线程数

  • IO密集型,线程不一直在执行任务,则可能多的线程,CPU核数 / (1 - 阻塞系数) 阻塞系数在0.8 ~ 0.9左右

本文地址:https://blog.csdn.net/afeiererer/article/details/107631355

相关标签: 面试