java concurrent 并发包学习记录
未完待续
参考:
https://blog.csdn.net/wbwjx/article/details/57856045
https://blog.csdn.net/defonds/article/details/44021605#t19
http://www.blogjava.net/xylz/archive/2010/07/08/325587.html
请先参考上面的链接,本文只是作为记录我学习博客的过程
java.util.concurrent 包是专为 Java并发编程而设计的包。包下的所有类可以分为如下几大类:
locks部分:显式锁(互斥锁和速写锁)相关;
atomic部分:原子变量类相关,是构建非阻塞算法的基础;
executor部分:线程池相关;
collections部分:并发容器相关;
tools部分:同步工具相关,如信号量、闭锁、栅栏等功能;
脑图地址: http://www.xmind.net/m/tJy5,
Lock部分
类似于synchronized 的线程同步机制
自旋锁:如果获取锁未获取到,会一直循环查看是否锁被释放
互斥锁:如果获取锁未获取到,会进入睡眠状态等待
共享锁:只是一个标志,所有线程都等待这个标志是否满足,一旦满足,所有线程都被激活
ReentrantLock 可重入锁
可中断响应、锁申请等待限时、公平锁等机制,以及结合Condition使用
1.可中断响应:
当两个线程1,2分别持有锁A和锁B并等待锁B和锁A,这样就发生了死锁,但是ReentrantLock可中断线程,中断线程2后,线程2释放锁B并不在等待锁A,此时线程1获取锁执行任务,但是线程2也并没有完成工作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class LockTest1 { static class KillDeadlock implements Runnable{ public static ReentrantLock lock1 = new ReentrantLock(); public static ReentrantLock lock2 = new ReentrantLock(); int lock; public KillDeadlock(int lock){ this.lock = lock; } @Override public void run() { try { if (lock ==1){ lock1.lockInterruptibly(); try { Thread.sleep(5000); }catch (InterruptedException e){ } lock2.lockInterruptibly(); }else { lock2.lockInterruptibly(); try { Thread.sleep(5000); } catch (InterruptedException e) { } lock1.lockInterruptibly(); } } catch (InterruptedException e) { e.printStackTrace(); }finally { if (lock1.isHeldByCurrentThread())lock1.unlock(); if (lock2.isHeldByCurrentThread())lock2.unlock(); System.out.println(Thread.currentThread().getId()+"退出!"); } } } public static void main(String[] args) throws Exception{ KillDeadlock k1 = new KillDeadlock(1); KillDeadlock k2 = new KillDeadlock(2); Thread t1 = new Thread(k1); Thread t2 = new Thread(k2); t1.start();t2.start(); Thread.sleep(10000); t1.interrupt(); } }
2.锁申请限时等待
可以使用tryLock()或tryLock(long timeout, TimeUtil unit) 方法进行一次限时的锁等待。
前者如果获取不到锁,会立即返回false,后者等待一段时间后返回false
3.公平锁
公平锁会按照时间先后顺序,先等待的先得到锁,而且不会产生饥饿锁,只要排队等待,最终能得到获取锁的机会
4.Condition 配合使用
如果获取锁后,发现部分参数不满足后面执行的条件,可以调用condition的await方法,继续等待,等待其他线程修改参数后,继续执行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class ReentrantLockWithConditon implements Runnable{ public static ReentrantLock lock = new ReentrantLock(true); public static Condition condition = lock.newCondition(); @Override public void run() { lock.newCondition(); try { lock.lock(); System.err.println(Thread.currentThread().getName() + "-线程开始等待..."); condition.await(); System.err.println(Thread.currentThread().getName() + "-线程继续进行了"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) throws InterruptedException { ReentrantLockWithConditon test = new ReentrantLockWithConditon(); Thread t = new Thread(test, "线程ABC"); t.start(); Thread.sleep(1000); System.err.println("过了1秒后..."); lock.lock(); condition.signal(); // 调用该方法前需要获取到创建该对象的锁否则会产生 // java.lang.IllegalMonitorStateException异常 lock.unlock(); } } --------------------- 作者:Somhu 来源:CSDN 原文:https://blog.csdn.net/Somhu/article/details/78874634 版权声明:本文为博主原创文章,转载请附上博文链接!
ReadWriteLock 读写锁
允许多个线程在同一时间对特定资源进行读取,但同一时间内只能有一个线程对其写入
实现类:ReentrantReadWriteLock
- 如果没有任何写操作锁定,那么可以有多个读操作锁定该锁
- 如果没有任何读操作或者写操作,只能有一个写线程对该锁进行锁定。
CountDownLatch 闭锁
基于共享锁实现。允许一个或者多个线程等待某个事件的发生。CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。
CyclicBarrier 循环锁
可循环调用,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。所谓屏障点就是一组任务执行完毕的时刻。
Atomic 部分
原子性包装
将数据进行原子性封装,变量级别的同步控制,同一时间只能有一个线程操作
Collections 部分
Queue 队列:
BlockingQueue extends Queue 阻塞队列
使用场景: 一个线程生产对象,另外一个线程消费对象:
有限的队列,队列满时,put会阻塞,队列空时,take会阻塞
SpecialValue : 如果操作无法执行,将返回一个特定的值,通常是true/false
注意:无法插入null
数据结构导致,除了获取开头和结尾之外的其他位置效率都不高
ArrayBlockingQueue 有界的阻塞队列
ConcurrentMap 线程安全Map