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)公平锁、非公平锁

[java] view plaincopy
  1. Lock l = ...;   
  2. l.lock();  
  3. try {  
  4.     …  
  5. finally {  
  6.     l.unlock();  
  7. }  
  8.  Lock lock = ...;  
  9.  if (lock.tryLock()) {  
  10.      try {  
  11.          …  
  12.      } finally {  
  13.          lock.unlock();  
  14.      }  
  15.  } else {  
  16.      …  
  17.  }  


5.Condition

await、signal、signalAll

[java] view plaincopy
  1. class BoundedBuffer {  
  2.    final Lock lock = new ReentrantLock();  
  3.    final Condition notFull  = lock.newCondition();   
  4.    final Condition notEmpty = lock.newCondition();   
  5.    final Object[] items = new Object[100];  
  6.    int putptr, takeptr, count;  
  7.    public void put(Object x) throws InterruptedException {  
  8.      lock.lock();  
  9.      try {  
  10.        while (count == items.length)   
  11.          notFull.await();  
  12.        items[putptr] = x;   
  13.        if (++putptr == items.length) putptr = 0;  
  14.        ++count;  
  15.        notEmpty.signal();  
  16.      } finally {  
  17.        lock.unlock();  
  18.      }  
  19.    }  
  20.    public Object take() throws InterruptedException {  
  21.      lock.lock();  
  22.      try {  
  23.        while (count == 0)   
  24.          notEmpty.await();  
  25.        Object x = items[takeptr];   
  26.        if (++takeptr == items.length) takeptr = 0;  
  27.        --count;  
  28.        notFull.signal();  
  29.        return x;  
  30.      } finally {  
  31.        lock.unlock();  
  32.      }  
  33.    }   
  34.  }  


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)代码

[java] view plaincopy
  1. class A {  
  2.     private volatile String testField=“test”;  
  3. }  
  4. A a = new A();  
  5. 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)主要用于池技术

[java] view plaincopy
  1. class ObjectPool {  
  2.     private Semaphore permits;  
  3.         public ObjectPool(int count) {  
  4.         permits = new Semaphore(count);  
  5.         }  
  6.        public Object borrowObject() {  
  7.        permits.acquire();  
  8.        //fetch object from pool and return  
  9.        }  
  10.        public boolean returnObject(Object object) {  
  11.            //put object into pool  
  12.            permits.release();  
  13.     }  
  14. }  

 

13.CountDownLatch

(1)方法
   a)构造函数(int count)
   b)countDown
   c)await
   d)count减到0时,await通过

(2)代码

[java] view plaincopy
  1. class WorkerRunnable implements Runnable {  
  2.    private final CountDownLatch doneSignal;  
  3.    private final int i;  
  4.    WorkerRunnable(CountDownLatch doneSignal, int i) {  
  5.       this.doneSignal = doneSignal;  
  6.       this.i = i;  
  7.    }  
  8.    public void run() {  
  9.       try {  
  10.         doWork(i);  
  11.         doneSignal.countDown();  
  12.       } catch (InterruptedException ex) {} // return;  
  13.    }  
  14.    void doWork() { ... }  
  15.  }  
  16.      CountDownLatch doneSignal = new CountDownLatch(N);  
  17.      Executor e = ...  
  18.      for (int i = 0; i < N; ++i) // create and start threads  
  19.        e.execute(new WorkerRunnable(doneSignal, i));  
  20.      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)

原创粉丝点击