《Java源码分析》:BlockingQueue2016年8月27日21:10:51,今天是学校报道的第一天,从今天开始,我也就研三了,哎,有时候只能感叹时间过的真快,自己的研究生生活只剩下最后一年。在最后的一年里,希望自己的一切都顺利吧,其中包括:找一份好的工作,顺利将手上的项目完成,顺利完成自己的毕设。说了这么多,还是开始本篇博文的正题吧。在前一段时间研究了下J.U.C包下面并发类库的原理,也都形成了相应的博文,唯独关于阻塞队列BlockingQueue以及它的4个实现类ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue
《Java源码分析》:LinkedBlockingQueueLinkedBlockingQueue是大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的。1、LinkedBlockingQueue的继承体系结构publicclassLinkedBlockingQueue<E>extendsAbstractQueue<E>implementsBlockingQueu
《Java源码分析》:BlockingQueue之PriorityBlockingQueue上面两篇博文分别介绍了BlockingQueue、ArrayBlockingQueue和LinkedBlockingQueue。这篇博文就来分析下PriorityBlockingQueue。1、PriorityBlockingQueue的继承体系结构publicclassPriorityBlockingQueue<E>extendsAbstractQueue<E>implementsBlockingQueue<E>,java.io.Serializable也是继承了A
《Java源码分析》:PriorityQueue看了PriorityBlockingQueue的源码之后,发现这个类的实现是基于二叉堆来实现的,然而自己以前对二叉堆基本上没有认真的研究过,这是自己第一次看到关于二叉堆的“插入元素”、“取出元素”等相关操作的一个具体实现。于是,想想,PriorityQueue里面的内部实现也应该是这样的,因此也就看了下PriorityQueue的源码,下面一点点的进行介绍。有了PriorityBlockingQueue类中关于二叉堆的相关操作的基础,看PriorityQueue类就比较简单了。1、PriorityQueue的继承体系publicclassPrio
《Java源码分析》:线程池Future、RunnableFuture、FutureTask在使用ThreadPoolExecutor使用submit提交任务后然后交给线程池中的线程去执行,是吧在ThreadPoolExecutor(其实是在AbstractExecutorService中)有如下几个submit方法,publicFuture<?>submit(Runnabletask){if(task==null)thrownewNullPointerException();RunnableFuture<Void>ftask=newTaskFor(task,null)
《Java线程池》:任务拒绝策略在没有分析线程池原理之前先来分析下为什么有任务拒绝的情况发生。这里先假设一个前提:线程池有一个任务队列,用于缓存所有待处理的任务,正在处理的任务将从任务队列中移除。因此在任务队列长度有限的情况下就会出现新任务的拒绝处理问题,需要有一种策略来处理应该加入任务队列却因为队列已满无法加入的情况。另外在线程池关闭的时候也需要对任务加入队列操作进行额外的协调处理。RejectedExecutionHandler提供了四种方式来处理任务拒绝策略1、直接丢弃(DiscardPolicy)2、丢弃队列中最老的任务(DiscardOldestPolicy)。3、抛异常(Abort
《Java源码分析》:线程池ThreadPoolExecutorThreadPoolExecutor是ExecutorService的一张实现,但是是间接实现。ThreadPoolExecutor是继承AbstractExecutorService。而AbstractExecutorService实现了ExecutorService接口。在介绍细节的之前,先介绍下ThreadPoolExecutor的结构1、线程池需要支持多个线程并发执行,因此有一个线程集合Collection来执行线程任务;2、很显然在多个线程之间协调多个任务,那么就需要一个线程安全的任务集合,同时还需要支持阻塞、超时操作,
Executors类中创建线程池的几种方法的分析要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。1、newFixedThreadPool:创建固定大小的线程池。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。/*函数功能:创建一个固定长度的的线程池,用于保存任务的阻塞队列为无限制长度的LinkedBlockingQueue。线程池中的线程将会一直存在除非线程池shutdown,即线程池中的线程没有受到存活时间的限制。
《Java线程池》:Executor生命周期我们知道线程是有多种执行状态的,同样管理线程的线程池也有多种状态。JVM会在所有线程(非后台daemon线程)全部终止后才退出,为了节省资源和有效释放资源关闭一个线程池就显得很重要。有时候无法正确的关闭线程池,将会阻止JVM的结束。线程池Executor是异步的执行任务,因此任何时刻不能够直接获取提交的任务的状态。这些任务有可能已经完成,也有可能正在执行或者还在排队等待执行。因此关闭线程池可能出现一下几种情况:1、平缓关闭:已经启动的任务全部执行完毕,同时不再接受新的任务2、立即关闭:取消所有正在执行和未执行的任务另外关闭线程池后对于任务的状态应该有
《Java线程池》Executor以及Executors线程池的相关类的体系结构如下:先看Executor接口,是最根上的接口publicinterfaceExecutor{/**Executesthegivencommandatsometimeinthefuture.Thecommand*mayexecuteinanewthread,inapooledthread,orinthecalling*thread,atthediscretionofthe{@codeExecutor}implementation.*翻译:1、任务可能在将来的某个时刻被执行,即可能不是立即执行2、任务可能在新的线程中
《Java源码分析》:CountDownLatchLatch:闭锁。有人把Latch比喻成是一个门,在门打开之前,所有想进门的线程都被阻塞,在门打开之后,所有想进门的线程全部通过,且门打开之后就不能再关闭。CountDownLatch是一个同步辅助类,允许一个或多个线程等待直到其它线程的一些操作已经准备完成。CountDownLatch是JDK5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。即C
《Java源码分析》:ExchangerExchanger类用于两个线程之间交换数据。Exchanger类只有两个方法:1、Vexchange(Vx)等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。API给出的详细说明如下:publicVexchange(Vx)throwsInterruptedException等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。如果另一个线程已经在交换点等待,则出于线程调度目的,继续执行此线程,并接收当前线程传入的对象。当前线程立即返回,接收其他线程传递的交换
《Java源码分析》:SemaphoreSemaphore是一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可。每个release()添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行计数,并采取相应的行动。说白了,Semaphore是一个计数器,在计数器不为0的时候对线程就放行,一旦达到0,那么所有请求资源的新线程都会被阻塞,包括增加请求到许可的线程,也就是说Semaphore不是可重入的。每一次请求一个许可都会导致计数器减少1,同样每次释放一个许可都会导
《Java源码分析》:CyclicBarrier(parttwo)在上篇博文中http://blog.csdn.net/u010412719/article/details/52156588,我们看了关于CyclicBarrier应用的一些例子,也得出的使用CyclicBarrier时的相关结论。回顾下我们在上篇博文中了解了关于CyclicBarrier的相关知识点如下:1、CyclicBarrier的用途是让一组线程互相等待,直到到达某个公共屏障点才开始继续工作。2、CyclicBarrier是可以重复利用的,CountDownLatch不可以重复利用3、在等待的只要有一个线程发生中断,则其
Java中synchronized关键字的使用对于关键字synchronized,研究起来,发现还是有许多让自己模糊的地方,网上也有很多篇博客对synchronized关键字的使用讲解的相当好,自己也受益匪浅。自己之所以还写一篇博客来介绍synchronized的目的只有一个:加深自己对synchronized的理解。写博客有时候确实是一个好的东西,往往研究某个知识点的时候,自己觉得弄懂了,但是过几天查不多就忘了模糊了,而写博客可以增加对知识点的理解和加深知识的记忆。synchronized关键字是解决多线程并发同步的方法之一。synchronized可以修饰如下几个方面。1、修饰一个代码块,
《Java源码分析》:Condition如下这篇博文讲解的Condition真心将的好,自己结合了源码也基本上对Condition有了一个大致的了解。写篇博客记录下。参考博客地址如下:http://ifeve.com/understand-condition/。API文档中对Condtion类列出的方法的说明如下1、voidawait()造成当前线程在接到信号或被中断之前一直处于等待状态。2、booleanawait(longtime,TimeUnitunit)造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。3、longawaitNanos(longnanosTimeou
《Java源码分析》:ReadWriteLock(第二部分)本篇博文主要介绍了ReentrantReadWriteLock内部实现。ReadWriteLock是一个接口,如下:publicinterfaceReadWriteLock{/***Returnsthelockusedforreading.*/LockreadLock();/***Returnsthelockusedforwriting.*/LockwriteLock();}ReentrantReadWriteLock是ReadWriteLock的实现类。此类的内部是借助于3个类来完成的。如下1、Sync。NonFairSync/Fa
《Java源码分析》:ReadWriteLock(第一部分)对象的方法中一旦加入synchronized关键字修饰,则任何时刻都只能有一个线程能够访问synchronized修饰的方法,例如:在Hashtable类中就是所有方法都使用了synchronized关键字修饰,这虽然解决了线程安全的问题,但是也降低了程序的并发性能(吞吐量)。在Hashtable中,即使我们使用get方法也只能只有一个线程能够访问,而本质上get方法并不修改内容,即使多个线程一起访问get方法也不存在线程不安全。基于此,就有了ReadWriteLock类,ReadWriteLock解决了这个问题.对于ReadWrit
《Java源码分析》:ReentrantLock.unlock释放锁上篇博客对ReentrantLock类中加锁的过程进行了一点介绍,可以在这里看到:http://blog.csdn.net/u010412719/article/details/52083731。本篇就对ReentrantLock.unlock释放锁进行一点点记录。ReentrantLock.unlock()API给出的介绍为:试图释放此锁。如果当前线程是此锁所有者,则将保持计数减1。如果保持计数现在为0,则释放该锁。如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException。下面就从源码的角
《Java源码分析》:ReentrantLock.lock锁机制AbstractQueuedSynchronizer这个类真的很难也很复杂,是构建锁以及实现其他相关同步类的基础框架。本来是没有打算来研究下这个类,但是由于想了解锁机制,因此,不可避免的需要研究它。但是这个类确实很难,自己看了几遍这个类也还是没有过多的看懂,本篇博文只能说是对自己看这个类的一点点理解和记录,若有错,请批评指正。基本的思想是表现为一个同步器,支持下面两个操作:1、获取锁:首先判断当前状态是否允许获取锁,如果是就获取锁,否则就阻塞操作或者获取失败,也就是说如果是独占锁就可能阻塞,如果是共享锁就可能失败。另外如果是阻塞线
《Java源码分析》:JavaNIO之ServerSocketChannel在上两篇博文中,主要从源码的角度粗略的介绍了Selector.open()和selector.select()方法的内部实现。由于Selector和ServerSocketChannel、SocketChannel配合使用,因此,有必要了解ServerSocketChannel、SocketChannel的内部实现。本篇博文主要来看下ServerSocketChannel。关于ServerSocketChannel类,我们主要从以下几个方法为切入点进行跟踪了解。1、ServerSocketChannelssc=Serv
JavaNIO之ServerSocketChannel/SocketChannelServerSocketChannel介绍JavaNIO中ServerSocketChannel是一个可以监听新进来的TCP连接的通道。既然是监听新的TCP连接,因此ServerSocketChannel一般用于服务器端,与Socket网络编程中的ServerSocket功能类似。在一般的编程实现的逻辑如下:/**既然是服务器端,肯定需要一个ServerSocketChannel来监听新进来的TCP连接。**/ServerSocketChannelserverSocketChannel=ServerSocketC
《Java源码分析》:JavaNIO之Selector(第一部分Selector.open())关于Selector类主要涉及两个重要的方法,如下:1、Selector.open()2、select()由于篇幅限制,这篇主要从源码的角度来介绍Selectorselector=Selector.open()背后主要做了什么,发生了什么。Selector类中的open()源码如下:publicstaticSelectoropen()throwsIOException{returnSelectorProvider.provider().openSelector();}函数功能:打开一个选择器。这个新
《Java源码分析》:JavaNIO之Selector(第二部分selector.select())上篇博文《Java源码分析》:JavaNIO之Selector(第一部分Selector.open())从源码的角度主要介绍了Selector.open()这个方法背后主要做了什么,发生了什么。本篇就是第二部分:从源码的角度来看下selector.select()背后做了些什么,怎么做的在看这篇博文之前,希望你已经阅读了上一篇博文:《Java源码分析》:JavaNIO之Selector(第一部分Selector.open())。因为这篇博文是在上篇博文的基础上来进行介绍的。为了更好的方便理解这篇
《Java源码分析》:JavaNIO之SelectionKey在ServerSocketChannel源码分析中我们知道当把一个channel注册到指定的Selector上时,实际上就是将(channel,selector)封装成了一个SelectionKey对象,并将此对象保存在了Selector对象中。SelectionKeyImplk=newSelectionKeyImpl((SelChImpl)ch,this);在JavaNIO的一些小Demo中,我们常常会看见这样的代码://当注册事件到达时,方法返回,否则该方法会一直阻塞selector.select();//获得selector中
JavaNIO之Selector这篇博文将来记录下自己JavaNIO中另一个重要的东西—-Selector。关于Selector确实不太好理解,自己也看了很多博客,到目前为止,自己对Selector还是没有弄清楚,感觉模模糊糊的。最主要的可能是没有找到对应的应用场景,不知道在上面地方能够用到Selector。关于Selector的相关介绍,并发编程网的这篇博文介绍的比较好:http://ifeve.com/selectors/。本篇博文就不对Selector进行介绍了,本着学习的态度,自己也来尝试通过写Demo来理解下Selector,于是就有了这篇博文。Selector例子本应用设想的场景是
《JavaNIO》:ChannelandBuffer(通道和缓冲区)从今天开始,自己将会了解下JavaNIO的相关知识,以及会看下相关的类库源码。和往常自己学习新知识之前,自己都会阅读网上的一些博文和资料,以使自己对这一块的知识有一个大致的了解,然后再按照自己感兴趣的点来研究一点点知识。关于JavaNIO这一块的知识,也是如此。关于JavaNIO涉及到三个重要的概念:1、Channel通道2、Buffer缓冲区3、Selector选择器在这篇文章的评论中对JavaNIO中的三个概念用一个比方来讲述,比较好理解,摘入如下:其中Channel对应以前的流,Buffer不是什么新东西,Selecto
《Java源码分析》:JavaNIO之Buffer在上篇博文中,我们介绍了JavaNIO中Channel和Buffer的基本使用方法,这篇博文将从源码的角度来看下Buffer的内部实现。在JavaAPI文档中,对Buffer的说明摘入如下:Buffer:是一个用于特定基本数据类型的容器。这里的特定基本数据类型指的是:除boolean类型的其他基本上数据类型。缓冲区是特定基本数据类型元素的线性有限序列。除内容外,缓冲区饿基本属性还包括三个重要的属性,如下:1、capacity(容量):表示Buffer容量的大小。2、limit(限制):是第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负数
《Java源码分析》:LinkedHashMap最近也即将要参加校招,因此,就准备花几天的时间专门来将我们用的比较多的集合类的源码都看下,并以写博客的形式来记录相关思路。便于以后复习。前面刚看了下HashMap类的源码,博客在这里:http://blog.csdn.net/u010412719/article/details/51980632Hashtable类的源码分析,博客在这里:http://blog.csdn.net/u010412719/article/details/51972602此篇博客就是关于LinkedHashMap类的源码分析。1、LinkedHashMap的继承结构pu
《Java源码分析》:TreeMap今天把TreeMap的源码稍微看了下,TreeMap的内部是基于红黑树来完成的。由于红黑树确实在我们的实际编码过程中用的比较少,因此自己对红黑树的认知不是很深,只是稍微有点印象罢了。由于TreeMap是基于红黑树来完成,因此,首先先列出红黑树的5个性质:性质1:每个节点要么是红色,要么是黑色。性质2:根节点永远是黑色的。性质3:所有的叶节点都是空节点(即null),并且是黑色的。性质4:每个红色节点的两个子节点都是黑色。(从每个叶子到根的路径上不会有两个连续的红色节点)性质5:从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点。本文只是对Tree