一、介绍
AQS是J.U.C的核心,AQS是AbstractQueuedSynchronizer的简写。

1.使用Node实现FIFO队列,可以用于构建锁或者其他同步装置基础框架。
2.利用一个int类型表示状态。
3.使用方法是继承。
4.子类通过继承并实现它的方法管理其状态{acquire和release}的方法操纵状态。
5.可以同时实现排他锁和共享锁模式。
组件:CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock、Condition、FutureTask。
二、CountDownLatch
主要是await方法,countDown方法,await方法等待countDown减为0后执行后面的代码。wait方法还可以指定时间。
三、Semaphore
主要是acquire和release方法,主要用于有限资源。可以丢弃没有请求到资源的请求,tryAcquire方法,还可以设置超时时间。
四、CyclicBarrier
允许多个线程相互等待,当每个线程准备就绪时才能继续向下执行。如果await指定了超时时间,可能抛出异常导致中断,要继续执行可以捕捉异常。
五、ReentrantLock
1.ReentrantLock与synchronized区别:
- 可重复性:前者可重入。
- 锁实现:前者JDK实现,后者JVM实现。
- 性能区别:相差不大。推荐synchronized。
- 功能区别:方便性synchronized高,细腻度ReentrantLock高。
2.ReentrantLock独有功能:
- 可指定公平锁还是非公平锁
- 通过Condition类,可以分组唤醒需要唤醒的线程
- 通过能够中断等待锁的线程的机制,lock.lockInterruptibly()。
ReentrentReadWriteLock:在没有读锁和写锁时,可以加写锁;写入很少读取很多时,容易导致写线程饥饿。
StampedLock等。
六、FutureTask
Future可以监视目标线程调用call的情况,可以得到线程任务方法的返回值。FutureTask结合了Future和Callable等接口,功能强大,适合使用线程完成任务,关心任务结果及正常执行情况。
七、Fork/Join框架
主要采用工作窃取算法。
八、BlockingQueue
线程安全,适用于生产者-消费者场景。

1.ArrayBlockingQueue:容量有限,初始化指定容量。
2.DelayQueue:一般按元素过期的优先级排序,适用于定时任务等。
3.LinkedBlockingQueue:初始化不指定大小则是无边界的。
4.PriorityBlockingQueue:无边界队列,允许插入空对象,有排序的队列。
5.SynchronousQueue:只允许插入一个元素,插入后被阻塞,除非被另一个队列取走。
九、线程池
1.new Thread弊端:
- 每次new Thread新建对象。性能差。
- 线程缺乏管理,可能无限制的新建线程,相互竞争,可能占用过多系统资源导致死机或者OOM。
- 缺少更多功能,如更多执行、定期执行、线程中断。
2.线程池好处:
- 重用存在的线程,减少对象创建、消亡的开销,性能好。
- 可以有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。
- 提供定时执行、定期执行、单线程、并发数控制等功能。
3.ThreadPoolExecutor:
- corePoolSize:核心线程数量,
- maximunPoolSize:线程最大线程数
- workQueue:阻塞队列,存储等待执行的任务,对线程池允许影响重大。
运行的线程数少于corePoolSize,直接创建新线程处理任务,即使其他线程是控线的。线程数大于等于corePoolSize,且小于maximumPoolSize时,则只有当BlockingQueue队列满时,才创建新任务。若corePoolSize和maximumPoolSize大小相等,则创建的线程池大小固定,有线程提交且BlockingQueue还没有满时,则加入BlockingQueue等待有空闲线程取出任务。若运行的线程数量大于指定的最大线程数时,若BlockingQueue也满了,则通过拒绝策略参数指定策略去处理这个任务。
若想降低系统消耗,可以设置一个较大的队列容量和一个较小的线程池容量,降低线程处理任务的吞吐量。
- KeepAliveTime:线程没有任务执行时最多保持多久时间终止。
- unit:keepAliveTime的时间单位。
- threadFactory:线程工厂,创建线程。
- rejectHandler:拒绝策略,有四种策略:直接抛出异常、调用线程执行任务、抛弃阻塞队列中最靠前的任务并执行当前任务、直接丢弃当前任务。

- execute():提交任务给线程池执行
- submit():提交任务,能够返回执行结果execute+Future
- shutdown():关闭线程池,等待任务都执行完
- shutdownNow():关闭线程池,不等待任务执行完。
- getTaskCount():线程池已执行和未执行的任务总数
- getCompletedTaskCount():已完成的任务数量
- getPoolSize():线程池当前线程数量
-
getActiveCount():当前线程池中正在执行任务的线程数量
线程池类图
- Executors.newCachedThreadPool:可缓存的线程池,如果线程池长度超过处理的需要,可以灵活回收空闲线程;如果没有可以回收的,就新建线程。
- Executors.newFixedThreadPool:创建一个定长线程池,可以控制线程的最大并发数,超出的线程会在队列中等待。
- Executors.newScheduledThreadPool:创建定长线程池,支持定时任务和周期任务。
- Executors.newSingleThreadExecutor:创建单线程线程池,保证任务按指定顺序执行。
合理配置
- CPU密集型任务,需要尽量压榨CPU,参考值可以设为NCPU+1
- IO密集型任务,参考值可以设置为2*NCPU
网友评论