java线程技术分享,java多线程技术点( 五 )


生产者正在生产第3个商品
生产者正在生产第4个商品
生产者正在生产第5个商品
customer正在消费第1个商品===
*/
2.2.3 LinkedBlockingQueue
基于链表的阻塞队列,内部也维护了一个数据缓冲队列 。需要我们注意的是如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小 。
LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了 。
2.2.4 LinkedBlockingQueue和ArrayBlockingQueue的主要区别

  • ArrayBlockingQueue的初始化必须传入队列大小,LinkedBlockingQueue则可以不传入 。
  • ArrayBlockingQueue用一把锁控制并发,LinkedBlockingQueue俩把锁控制并发,锁的细粒度更细 。即前者生产者消费者进出都是一把锁,后者生产者生产进入是一把锁,消费者消费是另一把锁 。
  • ArrayBlockingQueue采用数组的方式存取,LinkedBlockingQueue用Node链表方式存取 。
2.2.5handler拒绝策略
Java提供了4种丢弃处理的方法,当然你也可以自己实现,主要是要实现接口:RejectedExecutionHandler中的方法 。
  • AbortPolicy:不处理,直接抛出异常 。
  • CallerRunsPolicy:只用调用者所在线程来运行任务,即提交任务的线程 。
  • DiscardOldestPolicy:LRU策略,丢弃队列里最近最久不使用的一个任务,并执行当前任务 。
  • DiscardPolicy:不处理,丢弃掉,不抛出异常 。
2.2.6线程池五种状态
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
RUNNING:在这个状态的线程池能判断接受新提交的任务,并且也能处理阻塞队列中的任务 。
SHUTDOWN:处于关闭的状态,该线程池不能接受新提交的任务,但是可以处理阻塞队列中已经保存的任务,在线程处于RUNNING状态,调用shutdown方法能切换为该状态 。
STOP:线程池处于该状态时既不能接受新的任务也不能处理阻塞队列中的任务,并且能中断现在线程中的任务 。当线程处于RUNNING和SHUTDOWN状态,调用shutdownNow方法就可以使线程变为该状态 。
TIDYING:在SHUTDOWN状态下阻塞队列为空,且线程中的工作线程数量为0就会进入该状态,当在STOP状态下时,只要线程中的工作线程数量为0就会进入该状态 。
TERMINATED:在TIDYING状态下调用terminated方法就会进入该状态 。可以认为该状态是最终的终止状态 。
回到线程池创建ThreadPoolExecutor,我们了解了这些参数,再来看看ThreadPoolExecutor的内部工作原理:
java线程技术分享,java多线程技术点

文章插图
  • 判断核心线程是否已满,是进入队列,否:创建线程
  • 判断等待队列是否已满,是:查看线程池是否已满,否:进入等待队列
  • 查看线程池是否已满,是:拒绝,否创建线程
2.3深入理解ThreadPoolExecutor
进入Execute方法可以看到:
public void execute(Runnable command) {
if (command == )
throw new PointerException;
int c = ctl.get;
//判断当前活跃线程数是否小于corePoolSize,如果小于,则调用addWorker创建线程执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get;
}
//如果不小于corePoolSize,则将任务添加到workQueue队列 。
if (isRunning(c) && workQueue.offer(command)) {

推荐阅读