多线程性能问题
线程调度
锁竟争、IO读写等
- 上下文切换:上下文切换会挂起当前正在执行的线程并保存当前的状态,然后找到要执行的代码,唤醒下一个线程。(考虑简单计算情况)
- 缓存失效:切换其它线程,cpu原有的缓存可能就失效,需要重新缓存新的数据(通常线程调试器会设置最小执行时间,以减少上下文切换的次数)
线程协作
避免数据错乱(禁止编译器和CPU的重排序优化)同步数据(工作内存flush到主存,再refresh到其它线程工作内存)
线程池优点
创建线程开销
系统开销(任务比较简单的话,有可能使创建和销毁用资源比线程执行本身更大)、占用一定内存等资源,上下文切换,稳定性,垃圾回收压力
线程池好处
- 解决线程生命周期系统开销问题,加快响应速度
- 统筹内存和CPU的使用
- 统一管理资源
队列
阻塞队列 BlockingQueue
通常使用RenntrantLock以及它的Condition来实现
- ArrayBlockingQueue:容量满了,不会扩容 ReentrantLock+两个Condition,读写要先获得独占锁才能进行下一步。 读时队列为空,则线程进行读线程专属的notEmpty的Condition的队列中排队,等待写线程写入新的元素 写时队列为满,写线程进行写线程专属的notFull队列中排队,等待读线程将队列元素移除并腾出空间
- LinkedBlockingQueue:无界 内部有两把锁,分别锁住队列的头和尾
- SynchronousQueue:容量不是1,它不需要执行元素,直接传递
- DelayQueue:底层使用PriorityBlickingQueue实现
- PriorityBlockingQueue:支持优先级的无界阻塞队列
- LinkdedTransferQueue
阻塞方法:
- take:获取并移除队列头结点,无数据则阻塞
- put:队列未满,正常插入,队列已满,则阻塞
抛出异常方法:
- add
- remove
- element:返回队首,不删除
返回结果,不抛出异常
- offer:插入一个元素,成功返回true;可带超时时间
- poll:移除并返回头节点,失败返回null,失败返回null;可带超时时间
- Peek:返回头结点,不移除
非阻塞队列 ConcurrentLinkedQueue
内部使用CAS非阻塞算法+重试实现———->不需要阻塞,并且并发不是特别剧烈的场景
原子类
Atomic+基本类型
AtomicInteger
AtomicLong
AtomicBoolean
AtomicArray+基础类型
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
Atomic+?+Reference
AtomicReference
AtomicStampedReference:添加了时间戳,解决了ABA问题
AtomicMarkableReference:多了一个绑定的Boolen值,可用于表示此对象已删除的场景
Atoimc+?+FieldUpdater
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater