J.U.C包介绍
来源:互联网 发布:软件测试原则 编辑:程序博客网 时间:2024/05/29 13:05
一、包结构
1.线程池
2.同步集合
a)
BlockingQueue
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
DelayQueue
SynchronousQueue
ConcurrentLinkedQueue
b)
ConcurrentMap
ConcurrentHashMap
c)
CopyOnWriteArrayList
CopyOnWriteArraySet
d)
CountDownLatch
CyclicBarrier
Exchanger
Semaphore
3.锁
J.U.C的locks包
4.原子操作
J.U.C的atomic包中的类
(1)计数器:AtomicBoolean, AtomicInteger, AtomicLong
(2)域更新器(基于反射,用于已有类的volatile域的更新):AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater
(3)数组:AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray
(4)引用:AtomicReference, AtomicStampedReference, AtomicMarkableReference
5.辅助类
(1)CancellationException
(2)ExecutionException
(3)TimeoutException
(4)RejectedExecutionException
(5)TimeUnit
(6)BrokenBarrierException
二、J.U.C中锁和内部锁比较
1.内部锁synchronized、wait、notify/notifyAll
2.J.U.C中锁Lock、Condition
3.比较
(1)三要素:锁、条件、等待队列
(2)锁:synchronized vs Lock
(3)条件:wait, notify/notifyAll vs Condition.await, signal/signalAll
(4)等待队列:锁对象 vs Condition
4.J.U.C中锁优劣
(1)优:一个锁上可以有多个条件及等待队列;性能好;
(2)劣:不易用,容易出错(如:未在finally中写lock.unlock)
三、类功能一览
1.ThreadPoolExecutor
(1)构造函数:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
(2)参数解释
corePoolSize:核心池大小
maximumPoolSize:池最大大小
keepAliveTime:无工作线程的存活时间
unit:时间的单位
workQueue:保持任务的队列
threadFactory:用于创建线程的工厂
handler:拒绝执行的处理类
(3)内部逻辑
初始时,由于线程数未达到corePoolSize,所以线程数不断增加,用来处理任务;当达到corePoolSize时,会将任务放入workQueue中;如果workQueue也满了,那么再次添加线程处理任务,直到线程数为maximumPoolSize;如果此时再有任务提交,就会调用reject来进行相应的处理;当线程空闲时,会根据keepAliveTime进行线程回收
(4)四种拒绝策略
CallerRunsPolicy:由调用者线程来处理任务
AbortPolicy:直接抛出RejectedExecutionException
DiscardPolicy:不执行任务,直接抛弃
DiscardOldestPolicy:移除任务队列的头任务
2.Executors
(1)生成ExecutorService的工厂类
(2)newSingleThreadExecutor() :corePoolSize=maximumPoolSize=1,workQueue=LinkedBlockingQueue(容量是Integer.MAX_VALUE)
(3)newCachedThreadPool():corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,workQueue=SynchronousQueue(容量是0)
(4)newFixedThreadPool(int nThreads):corePoolSize=maximumPoolSize=nThreads,keepAliveTime=0,workQueue=LinkedBlockingQueue(容量是Integer.MAX_VALUE)
(5)newSingleThreadScheduledExecutor():单线程,延迟执行任务
(6)newScheduledThreadPool(int corePoolSize):corePoolSize,maximum=Integer.MAX_VALUE,keepAliveTime=0,workQueue=DelayedWorkQueue
3.Future,FutureTask
(1)FutureTask实现Future
(2)表示一个在线程池中执行任务的返回结果
(3)AbstractExecutorService的newTaskFor方法
(4)Future
a)cancel 取消执行
b)get 取结果
4.ReentrantLock
(1)可重入锁:在同一个线程内,可以进行任意次数的加锁
(2)方法:lock、unlock、tryLock、newCondition
(3)公平锁、非公平锁
- Lock l = ...;
- l.lock();
- try {
- …
- } finally {
- l.unlock();
- }
- Lock lock = ...;
- if (lock.tryLock()) {
- try {
- …
- } finally {
- lock.unlock();
- }
- } else {
- …
- }
5.Condition
await、signal、signalAll
- class BoundedBuffer {
- final Lock lock = new ReentrantLock();
- final Condition notFull = lock.newCondition();
- final Condition notEmpty = lock.newCondition();
- final Object[] items = new Object[100];
- int putptr, takeptr, count;
- public void put(Object x) throws InterruptedException {
- lock.lock();
- try {
- while (count == items.length)
- notFull.await();
- items[putptr] = x;
- if (++putptr == items.length) putptr = 0;
- ++count;
- notEmpty.signal();
- } finally {
- lock.unlock();
- }
- }
- public Object take() throws InterruptedException {
- lock.lock();
- try {
- while (count == 0)
- notEmpty.await();
- Object x = items[takeptr];
- if (++takeptr == items.length) takeptr = 0;
- --count;
- notFull.signal();
- return x;
- } finally {
- lock.unlock();
- }
- }
- }
6.ReentrantReadWriteLock
(1)读写分离
(2)readLock
(3)writeLock
(4)读锁不可升级
a)错误方式:readLock.lock,writeLock.lock,死锁
b)正确方式:readLock.lock,readLock.unlock,writeLock.lock
(5)写锁可降级
a)writeLock.lock,readLock.lock,writeLock.unlock,降级为读锁
7.AtomicInteger
(1)compareAndSet
(2)incrementAndGet
(3)decrementAndGet
(4)……
(5)可用于计数器之类的用途
8.AtomicReferenceFieldUpdater
(1)static newUpdater(Class<U> tclass, Class<W> vclass, String fieldName)
a)tclass 对象类
b)vclass 域类
c)fieldName 域名
(2)用于已有类的volatile域的原子更新
(3)代码
- class A {
- private volatile String testField=“test”;
- }
- A a = new A();
- AtomicReferenceFieldUpdater.newUpdater(A.class, String.class, “testField”).compareAndSet(a, “test”, “testNew”);
9.ArrayBlockingQueue
(1)锁条件
a)notEmpty
b)notFull
(2)方法
a)put:notFull.await, notEmpty.singal
b)take:notEmpty.await, notFull.singal
c)offer(阻塞或不阻塞): notFull.await, notEmpty.singal
d)poll (阻塞或不阻塞) : notEmpty.await, notFull.singal
10.ConcurrentHashMap
(1)实现方式
a)将ConcurrentMap分为许多个segment,每个segment其实就相当于一个普通的Map(HashMap实现:通过hash算法先找到在数组的哪个位置,如果冲突,利用链表方式解决冲突)
b)计算key的hash值,将其分到一个segment上,获取这个segment的锁,然后再对这个segment进行更新
c)默认为16个segment
(2)增加了几个方法,如:V putIfAbsent(K key, V value);
11.CopyOnWriteArrayList
(1)适用于大量读,少量写的情况
(2)实现
a)内部使用了ReentrantLock
b)当对其修改时,加锁,复制整个底层数组,并进行修改,最后切换底层数组引用
12.Semaphore
(1)信号量的实现
(2)方法
a)构造函数(int permits)
b)acquire(int permits):得到许可
c)release(int permits):释放许可
d)tryAcquire(int permits)
(3)主要用于池技术
- class ObjectPool {
- private Semaphore permits;
- public ObjectPool(int count) {
- permits = new Semaphore(count);
- }
- public Object borrowObject() {
- permits.acquire();
- //fetch object from pool and return
- }
- public boolean returnObject(Object object) {
- //put object into pool
- permits.release();
- }
- }
13.CountDownLatch
(1)方法
a)构造函数(int count)
b)countDown
c)await
d)count减到0时,await通过
(2)代码
- class WorkerRunnable implements Runnable {
- private final CountDownLatch doneSignal;
- private final int i;
- WorkerRunnable(CountDownLatch doneSignal, int i) {
- this.doneSignal = doneSignal;
- this.i = i;
- }
- public void run() {
- try {
- doWork(i);
- doneSignal.countDown();
- } catch (InterruptedException ex) {} // return;
- }
- void doWork() { ... }
- }
- CountDownLatch doneSignal = new CountDownLatch(N);
- Executor e = ...
- for (int i = 0; i < N; ++i) // create and start threads
- e.execute(new WorkerRunnable(doneSignal, i));
- doneSignal.await();
14.CyclicBarrier
(1)一组线程互相等待,直到某个屏障点
(2)方法
a)CyclicBarrier(int parties)
b)CyclicBarrier(int parties, Runnable barrierAction)
c)await
d)reset:重置到初始值,可重复使用
e)await的线程数量到parties时,所有线程共同通过await,但只由最后一个线程执行barrierAction
四、锁、非阻塞算法和CAS
1.比较
(1)锁:悲观策略;需要上下文切换
(2)非阻塞算法:乐观策略;冲突检测,硬件支持;自旋等待,不需要上下文切换;高并发下,资源竞争过于激烈
2.CAS (compare and set)
(1)原理:内存值V,旧值A,新值B;当V==A时,才将内存值更新为B;否则,在循环中重试,直到成功为止
(2)J.U.C中atomic包的类实现了CAS的操作
3.atomic包中的类
(1)计数器:AtomicBoolean, AtomicInteger, AtomicLong
(2)域更新器(基于反射,用于已有类的volatile域的更新):AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater
(3)数组:AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray
(4)引用:AtomicReference, AtomicStampedReference, AtomicMarkableReference
五、线程活跃度
1.死锁
(1)锁顺序不一致造成
(2)工具:jconsole,jstack
2.饥饿
(1)AQS中锁
a)公平锁(必须进入等待队列)
b)非公平锁(可以不进入等待队列)(吞吐量大,性能好)
3.活锁
(1)不正确的重试,而且不断重试(将不可修复的错误当成可修复的错误)
六、提升多线程性能的方法
1.减小锁的范围:使同步块尽可能的小
2.减小锁的粒度
(1)分拆锁:如果一个锁用于几个用途,则将其分拆成几个不同的锁
(2)分离锁:一个锁,再分成不同的部分(如:ConcurrentHashMap就分成了16锁,从而减少冲突的可能性)
3.减少上下文切换
(1)启动适当的线程数
(2)锁-->非阻塞
七、多线程性能测试
1.垃圾回收
(1)保证垃圾回收在运行期间执行多次,测试时间更长
(2)查看gc日志:-verbose:gc -Xloggc:/tmp/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps,确保测试期间gc多次运行
2.动态编译
(1)代码可能以字节码解释执行;当某部分代码运行多次后,编译为机器码,直接执行
(2)让代码首先”warm up”,即调用被测方法达到一定次数,然后再测试被测方法
(3)次数确定,-XX:+PrintCompilation开关,来查看某一方法在调用多少次后被编译,修改程序再次运行测试
3.代码路径:确保测试的代码路径和真实情况一致
4.竞争程度:确保测试的竞争程度和真实情况一致
5.dead code
(1)编译器会优化代码,从而消除一些你认为会执行的代码,这些代码对结果没有任何影响
(2)可以加入类似于System.out.print()这样的代码来防止编译器优化掉你的代码(会增加一点点性能开销,不会增加IO开销,因为在调用System.out.println时才产生IO操作)
6.静态代码分析工具(除错,findbugs)
- J.U.C包介绍
- J.U.C包介绍
- J.U.C包简介
- J.U.C-包下的类分类
- J.U.C体系
- J.U.C
- “J.U.C”:ReentrantReadWriteLock
- “J.U.C”:Condition
- J.U.C重入锁
- J.U.C之Future
- J.U.C之CopyOnWriteArrayList
- J.U.C之CountDownLatch
- J.U.C之CyclicBarrier
- J.U.C之Semaphore
- J.U.C之Exchanger
- J.U.C之Lock
- J.U.C之Condition
- “J.U.C”:Condition (r)
- 独立游戏新闻和评论网站
- Oracle之/* ASSIST */用法
- poj 2411 Mondriaan's Dream(状态压缩DP)
- 变更控制流程图(PMP第五版)
- windows编程模型
- J.U.C包介绍
- POJ 2245 Lotto (枚举)
- poj——1019(数学)
- 关于C/C++函数指针声明的理解
- Steve Yegge:Google面试秘籍
- build/core/base_rules.mk:195: already define
- URAL 1635
- 分类算法之决策树
- Linux内核高端内存