本章将介绍一些常用的并发工具包,主要讲大概内容,做一个引导学习的作用,想要具体看使用用法可以参考其他博客。
一、fork/join
1、概念
采用了“分而治之”的思想,将一个任务拆分成最小单远,进行处理之后,在进行合并
2、使用fork/join的标准范式
我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork和join的操作机制,通常我们不直接继承ForkjoinTask类,只需要直接继承其子类。
1. RecursiveAction,用于没有返回结果的任务
2. RecursiveTask,用于有返回值的任务
task要通过ForkJoinPool来执行,使用submit 或 invoke 提交,两者的区别是:invoke是同步执行,调用之后需要等待任务完成,才能执行后面的代码;submit是异步执行。
join()和get方法当任务完成的时候返回计算结果
延伸:并归排序法就是采用了“分而治之”的思想,实现排序的效率较高
参考文档:https://blog.youkuaiyun.com/tyrroo/article/details/81390202
二、countdownlatch和cyclicBarrier
1、概念
countdownlatch:一个(多个)线程,必须等待其他线程执行完成后才能继续执行。
cyclicBarrier:多个线程相互等待,知道所有线程都完成,才能进行各自的后面的任务。
2、应用场景
countdownlatch:
(1)开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段。
(2)应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
cyclicbarrier:
(1)CyclicBarrier可以用于多线程计算数据,最后合并计算结果的应用场景。
3、区别
CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
参考文献:https://www.cnblogs.com/liun1994/p/7396026.html
http://www.importnew.com/21889.html
三、callable
1、概念
也是实现线程的一个接口,主要用于并发编程。
2、和runnable区别和相同点
区别:
实现callable的类可以有返回值,runnable接口没有返回值
相同点:
都有方法可以阻塞主线程
四、原子操作CAS
1、概念
CAS类比于乐观锁,先执行,在进行判断是否存在多线程的争用问题。
CAS操作涉及到三个值:当前主内存中的值V,线程本地内存中的值E和待更新的值U。如果当前内存中的值V等于预期值E,则将内存中的值更新为U,CAS操作成功。否则不更新CAS操作失败,然后自旋,直到成功。流程图如下:
2、产生问题
1、ABA问题
2、消耗cpu资源
3、只保证了一个共享变量的操作
3、解决办法
1、ABA问题
加一个版本标记,比如JDK提供给我一个AtomicStampedReference就是通过对值加一个戳(stamp)来解决“ABA”问题的
2、只保证了一个共享变量的操作
JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象里来进行CAS操作
4.常用atomic类
最常用的就是atomicInteger,实现计数作用
五、显示锁LOCK
1、优点:
Java程序是靠synchronized关键字实现锁功能的,使用synchronized关键字将会隐式地获取锁,但是它将锁的获取和释放固化了,也就是先获取再释放。
2、使用范式
lock.lock();
try{
count++;
}finally{
lock.unlock();
}
3、实现类reentrantlock
1、实现了锁的可重入
2、对公平锁和非公平锁的理解(reentrantlock可通过构造函数实现公平锁和非公平锁)。非公平锁的效率更高。synchronize锁都是非公平锁
4、读写锁reentrantreadwritelock
读的时候可以实现资源的共享,写的时候实现线程的独占
5、condition
condition配合lock实现线程的等待和通知。condition.await(),和condition.signal()
6、了解LockSupport
六、aqs(abstractqueuedsychronizer)队列同步器
1、概念
队列同步器AbstractQueuedSynchronizer(以下简称同步器或AQS),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。并发包的大师(Doug Lea)期望它能够成为实现大部分同步需求的基础。
2、设计模式
1、模板方法模式
3、参考文档
http://ifeve.com/introduce-abstractqueuedsynchronizer/
七、并发工具类
1、hashmap和concurrenthashmap和hashtable区别
1、hashmap线程不安全,concurrenthashmap和hashtable安全
2、效率:hashmap>concurrenthashmap>hashtable
3、conrrenthashmap采用分段所的机制实现了线程安全,hashtable采用sychronized关键字实现线程安全
2、阻塞队列(blockingqueue)
1、作用
解耦
削峰
2、常用的阻塞队列
ArrayBlockingQueue、LinkedBlockingQueue、DelayQueue
八、线程池
1、优点
1、降低资源消耗
2、提高响应速度
3、提高线程的可管理性
2、线程池的工作机制
1、如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
2、如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
3、如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务。
4、如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用 RejectedExecutionHandler.rejectedExecution()方法。
3、合理地配置线程池
CPU密集型任务应配置尽可能小的线程,如配置Ncpu+1个线程的线程池。由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如2*Ncpu。
4、预定义线程池
1、FixedThreadPool
2、SingleThreadExecutor
3、CachedThreadPool
4、ScheduledThreadPoolExecutor
5、CompletionService