AbstractQueueSynchronizer
1.AbstractQueuedSynchronizer(以下简称AQS)是Java并发包提供的一个同步基础机制,是并发包中实现Lock和其他同步机制(如:Semaphore、CountDownLatch和FutureTask等)的基础。
2.AQS内部包含一个FIFO的同步等待队列,简单的说,没有成功获取控制权的线程会在这个队列中等待。
3.AQS内部管理了一个原子的int域作为内部状态信息,并提供了一些方法来访问该域,基于AQS实现的同步机制可以按自己的需要来灵活使用这个int域, 比如:ReentrantLock用它记录锁重入次数;CountDownLatch用它表示内部的count;FutureTask用它表示任务运行状 态(Running,Ran和Cancelled);Semaphore用它表示许可数量。
4.AQS提供了独占和共享两种模式。在独占模式下,当一个线程获取了AQS的控制权,其他线程获取控制权的操作就会失败;但在共享模式下,其他线程 的获取控制权操作就可能成功。并发包中的同步机制如ReentrantLock就是典型的独占模式,Semaphore是共享模式;也有同时使用两种模式 的同步机制,如ReentrantReadWriteLock。 AQS内部提供了一个ConditionObject类来支持独占模式下的(锁)条件,这个条件的功能与Object的wait和notify/notifyAll的功能类似,但更加明确和易用。
状态位+队列
ReentrantLock
1.与Synchronized相比较而言,ReentrantLock有以下优势:支持公平/非公平锁、支持可中断的锁、支持非阻塞的tryLock(可超时)、支持锁条件、可跨代码块使用(一个地方加锁,另一个地方解锁),总之比Synchronized更加灵活
ReentrantReadWriteLock
- ReentrantReadWriteLock提供了读写锁的机制,读锁使用AQS的共享模式,写锁使用独占模式。
- ReentrantReadWriteLock也支持公平/非公平锁。
- ReentrantReadWriteLock的写锁会阻塞读锁和写锁,读锁只会阻塞写锁。
- ReentrantReadWriteLock的写锁可以降级为读锁,但读锁不能升级为写锁。
CountDownLatch
- CountDownLatch称为闭锁。可以让一个或多个线程等待另外一个或多个线程执行完毕后再执行。
- CountDownLatch也是基于AQS构建,使用共享模式。
Semaphore
是一种基于计数的信号量,管理了一组许可。线程可以申请许可,当信号量中有许可时,线程申请成功,拿走一个许可;没有许可时, 线程阻塞等待其他线程用完了许可,归还给信号量。这个许可不是真正的许可(比如凭证),只是一个计数,线程也不会真正使用这些许可。
- Semaphore一般用来构建一些对象池,资源池之类的,比如数据库连接池。
- 可以创建一个count为1的Semaphore作为一种类似互斥锁的机制,也叫二元信号量,表示两种互斥状态。但和Lock有些区别,Lock只能又获取锁的线程来释放锁,而Semaphore允许其他线程来做释放动作。
- Semaphore也支持公平和非公平策略。
ArrayBlockingQueue
- ArrayBlockingQueue是一种基于数组实现的有界的阻塞队列。队列中的元素遵循先入先出(FIFO)的规则。新元素插入到队列的尾部,从队列头部取出元素。
- 和普通队列有所不同,该队列支持阻塞操作。比如从空队列中取元素,会导致当前线程阻塞,直到其他线程将元素放入队列;将元素插入已经满的队列,同样会导致当前线程阻塞,直到其他线程从队列中取出元素。
- ArrayBlockingQueue也支持公平和非公平策略(针对队列中元素的存取线程,也可认为是元素的生产者和消费者)。
不能为null insert extract
LinkedBlokingQueue
LinkedBlockingQueue是一种基于单向链表实现的有界的(可选的,不指定默认int最大值)阻塞队列。队列中的元素遵循先入先出(FIFO)的规则。新元素插入到队列的尾部,从队列头部取出元素。
ThreadPoolExecutor
ThreadPoolExecutor是JUC包中提供的线程池,使用ThreadPoolExecutor的好处一方面是能重用线程资源,避免重复创建 线程带来的开销;另一方面是ThreadPoolExecutor提供了内部资源(线程、任务)的管理功能,方便我们监控线程池工作状态。
4个状态:
- static final int RUNNING = 0; //表示正在运行。会接受新任务,并会处理任务队列中的任务。
- static final int SHUTDOWN = 1; //表示已经关闭。不接受新任务,但仍然会处理任务队列中的任务。
- static final int STOP = 2; //表示已经停止。不接受新任务,不处理任务队列中的任务,会中断正在执行的任务。
- static final int TERMINATED = 3; //在STOP的基础上,在加上所有的任务都已经结束。
一个任务队列,一个工作类集合,一些状态数据还有一个拒绝任务处理器。
execute,执行逻辑,
shutdown
shutdownnow
- * 1. 运行状态设置为STOP。
- * 2. 中断所有的工作线程,不仅仅是空闲的工作线程。
- * 3. 清空任务队列,并返回任务队列中的任务。
Woker类 ,poll,take
- Runnable getTask() {
- for (;;) {
- try {
- int state = runState;
- if (state > SHUTDOWN)
- return null; // 线程池已经停止或终止,获取不到任务。
- Runnable r;
- if (state == SHUTDOWN)
- r = workQueue.poll(); // 如果线程池已经关闭,还可以从任务队列中取任务。
- else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
- /*
- * 如果当前线程数量多于核心线程数量或者允许核心线程超时,
- * 才会调用带超时的poll方法,如果超时时间内无法获取任务
- * 那么当前worker后继就会被干掉了。
- */
- r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
- else
- r = workQueue.take(); //否则,调用take方法,阻塞直到有任务可以获取。
- if (r != null)
- return r;
- //如果没有获取到任务,检测一下当前worker是否可以退出。
- if (workerCanExit()) {
- if (runState >= SHUTDOWN)
- interruptIdleWorkers(); // 如果线程池已经关闭,中断空闲的worker。
- return null;
- }
- // Else retry
- } catch (InterruptedException ie) {
- // On interruption, re-check runState
- }
- }
- }
AbstractQueueSynchronizer的更多相关文章
- Effective Java通俗理解(持续更新)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- ReentrantLock原理学习
上文我们学习了ReentrantLock的基本用法,在最后我们留下了一个问题,ReentrantLock获取的锁是什么锁呢?本文我们就从源码的角度来一探究竟.本文涉及到的源码对应JDK版本为1.8. ...
- Java并发编程实战
代码中比较容易出现bug的场景: 不一致的同步,直接调用Thread.run,未被释放的锁,空的同步块,双重检查加锁,在构造函数中启动一个线程,notify或notifyAll通知错误,Object. ...
- 探究Java中的锁
一.锁的作用和比较 1.Lock接口及其类图 Lock接口:是Java提供的用来控制多个线程访问共享资源的方式. ReentrantLock:Lock的实现类,提供了可重入的加锁语义 ReadWrit ...
- Effective Java通俗理解(上)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- 《Java并发编程的艺术》--Java中的锁
No1: Lock接口 Lock lock = new ReentrantLock(); lock.lock(); try{ }finally{ lock.unlock(); } No2: 不要讲获取 ...
- Java多线程:AQS
在Java多线程:线程间通信之Lock中我们提到了ReentrantLock是API级别的实现,但是没有说明其具体实现原理.实际上,ReentrantLock的底层实现使用了AQS(AbstractQ ...
- java面试题:多线程与并发
多线程 关键词:线程池 Q:如何新建一个线程? 继承Thread,或者实现Runnable接口,或者通过Callable接口实现. Q:Callable怎么用? Callable可以作为FutureT ...
- javaWeb后端学习记录
java后端学习重点: 1.java语言特性: 基础知识,集合,多线程,并发,JVM,NIO,网络编程,设计模式. (★★★★★) jdk源码中有大量的数据结构与java语言细节.jdk源码着重看c ...
随机推荐
- 2016 - 1 - 23 json解析
一: json 1. 什么是json 1.1 json是一种轻量级的数据格式,一般用于数据交互. 1.2 服务器返回给客户端的数据,一般都是JSON或者XML格式(文件下载除外). 2. JS ...
- unity5.3.4之no android module loaded
参考http://www.cnblogs.com/shenggege/p/5165616.html 最近从unity5.1.3升级到5.3.4的时候,发现有个问题: system.io.file' d ...
- Windows Squid 安装配置
squid 可以做反向代理将系统中相对静态的页面进行缓存和负责均衡,提高网站访问速度,增强网站可用性.安全性.用户访问Squid 反向代理服务器的 IP 地址,这样客户端的 URL 请求将被发送到反向 ...
- Android ViewPager Fragment使用懒加载提升性能
Android ViewPager Fragment使用懒加载提升性能 Fragment在如今的Android开发中越来越普遍,但是当ViewPager结合Fragment时候,由于Androi ...
- Runloop之个人理解
Runloop之个人理解更像是一种线程等待机制,传统线程的消息传入机制,线程收到什么样的消息,就执行什么样的动作,如果是信号量队列型的,其实就基本实现了线程在无消息时挂住休眠;而不是在每隔一段时间就要 ...
- UVA340 猜数字游戏
一个经典的找数字位置正确并且找到正确数列中存在的数字而错误的序列存在但是不是正确位置的算法. 看似很难的算法,但是lrj却很简单解决. #include<cstdio> #define M ...
- AndroidStudio开发出现Warning:Gradle version 2.10 is required. Current version is 2.8. If u
Warning:Gradle version 2.10 is required. Current version is 2.8. If using the gradle wrapper, try ed ...
- 认识C++中的临时对象temporary object 分类: C/C++ 2015-05-11 23:20 137人阅读 评论(0) 收藏
C++中临时对象又称无名对象.临时对象主要出现在如下场景. 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象. Integer inte= Integer(5); ...
- unity, 播放循环背景音乐注意事项
循环背景音乐用wav格式,不要用mp3. 参考:http://answers.unity3d.com/questions/343057/how-do-i-make-unity-seamlessly-l ...
- Correlation Filter in Visual Tracking系列一:Visual Object Tracking using Adaptive Correlation Filters 论文笔记
Visual Object Tracking using Adaptive Correlation Filters 一文发表于2010的CVPR上,是笔者所知的第一篇将correlation filt ...