java.util.concurrent 并发工具包详解

零、Concurrent包概述
jdk5开始提供的 并发工具包,在其中提供了大量的和并发操作相关的工具,大大简化了java的多线程开发。


一、BlockingQueue - 阻塞式队列 不接受 null 元素
BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。


操作阻塞式队列的四组方法
抛异常  特定值    阻塞   超时
插入  add(o)  offer(o)  put(o)  offer(o, timeout, timeunit)
移除  remove(o)  poll(o)  take(o)  poll(timeout, timeunit)
检查  element(o)  peek(o) 


BlockingQueue
|- ArrayBlockingQueue
|- LinkedBlockingQueue


ArrayBlockingQueue
ArrayBlockingQueue 类实现了 BlockingQueue 接口。
ArrayBlockingQueue 是一个有界的阻塞队列,其内部实现是将对象放到一个数组里。
构造方法:
ArrayBlockingQueue(int capacity) 


案例:利用阻塞式队列 来实现 生产者 消费者 机制


LinkedBlockingQueue
LinkedBlockingQueue 类实现了 BlockingQueue 接口。
LinkedBlockingQueue 底层是链表 可以设置 最大容量 也可以不设置 如果不设置 默认最大容量为 Integer.MAX_VALUE 可以认为没有容量限制
构造方法:
LinkedBlockingQueue(int capacity)
LinkedBlockingQueue()

二、ConcurrentMap - 并发Map
ConcurrentMap是一种线程安全的Map


ConcurrentMap
| - ConcurrentHashMap


HashMap - 线程不安全 效率高
HashTable - 线程安全 效率低 已经过时 不推荐使用 --- 锁的是整个桶
ConcurrentHashMap - 线程安全 效率比较高   ---锁分段技术,加在正在操作的桶上


ConcurrentHashMap效率:
锁不是加载整个Map上,而是加在正在操作的桶上的,从而在桶的级别实现了并发 提高效率 
引入和读写锁,在并发读的过程中 可以并发 提升效率

三、CountDownLatch -- 闭锁 -- 线程递减锁
可以协调多个线程执行的先后顺序,非常便于实现 一个线程的执行需要等待另外一个或多个线程达到指定条件的需求。


构造方法:
CountDownLatch(int count) 
阻塞线程:
void await() 
递减数字:
void countDown() //没底调用count-1 减到0,则await阻塞被放开




四、CyclicBarrier -- 栅栏
CyclicBarrier是一个所有线程必须等待的一个栅栏,直到指定数量的线程都到达栅栏位置,然后所有线程才可以继续做其他事情。
构造方法 :
CyclicBarrier(int count)


到达栅栏开始等待:
void await();//当足够count个线程进入等待状态,栅栏同时打开阻塞,所有的线程一起向下执行


五、Exchanger -- 交换机
Exchanger 类表示一种两个线程可以进行互相交换对象的会和点
构造方法:
new Exchanger();
交换对象:
exchange(object)

六、Semaphore -- 信号量

计数信号量由一个指定数量的 "许可" 初始化。每调用一次 acquire(),一个许可会被调用线程取走。每调用一次 release(),一个许可会被返还给信号量。

        作用:经常用于限制获取某种资源的线程数量

构造方法:
Semaphore(int permits)
Semaphore(int permits, boolean fair) 

获取信号量:
void acquire()//如果信号量当前 值为0,则此方法阻塞 直到有release将信号量返回
释放信号量:
void release()//立即释放一个信号,无论是否之前获取过都可以调用此方法,不阻塞


功能1:控制一度重要的代码同一时间内 至多有 n个线程访问
功能2:在两个线程之间传递信号

七、ExecutorService -- ThreadPool -- 执行器服务、线程池

ExecutorService
|-ThreadPoolExecutor

线程池,用来共享线程,线程在需要的时候创建,用完后不销毁,而是存入线程池,则后续再需要使用线程时,可以直接从池中获取线程来使用,从而减少线程的开关次数,提升程序的性能。

                            

1.创建线程池
(1)通过构造方法创建线程池
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 
corePoolSize 核心池大小
maximumPoolSize 最大池大小
keepAliveTime 空闲的多余线程保持时间
unit 时间单位
workQueue 阻塞式队列
handler 拒绝服务助手


(2)通过工具类获取常用的线程池实现
Executors
newCachedThreadPool()  
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池
newSingleThreadExecutor() 
创建一个单一线程的线程池


2.执行任务
execute(Runnable)
Future submit(Runnable) //可以通过Future的get()方法来观察任务是否执行结束 --- 全部结束
Future submit(Callable) //可以用来观察任务是否执行结束 并且可以从线程内部带回返回值
invokeAny() //其中一个
invokeAll() //所有的

3.关闭线程池
shutdown()
ExecutorService 并不会立即关闭,但它将不再接受新的任务,而且一旦所有线程都完成了当前任务的时候,ExecutorService 将会关闭
shutdownNow()
这样会立即尝试停止所有执行中的任务, 并忽略掉那些已提交但尚未开始处理的任务。 无法担保执行任务的正确执行。可能它们被停止了,也可能已经执行结束。
八、Lock - 锁
是线程同步的机制 可以实现类似synchronized代码块的效果 但是比synchronized代码更灵活 更简单

ReentrantLock 

                    方法:

                    lock.lock()    上锁

                    lock.unlock(  )    解锁

ReadWriteLock 无论多少个读过来,都可以并发处理,写+写|读+写不能并发

                     这个和上面的用法稍有不同,

                       lock.readLock().lock();  上读锁

                       lock.readLock().unlock();  解除读锁

                       lock.writeLock().lock(); 上写锁

                       lock.writeLock().lock()  ;    解除写锁        







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值