摘要:实现初始化线程池数量策略并执行线程。二简述下从定义线程池,到其底层执行的简单流程简单定义了如上两句代码,自动创建个固定大小的线程的线程池,实现了接口的对象以后,自动启动线程并执行对象的方法。关键的调用类方法,管理线程池并执行任务。
一.类图说明
Executor接口类,执行Runnable接口execute。
ExecutorService接口类继承Executor接口,包含提交执行Runnable和Callable接口submit以及shutdown,invokeAll接口。
ScheduledExecutorService接口类继承ExecutorService接口,主要包含计划执行接口schedule,scheduleAtFixedRate以及scheduleWithFixedDelay。
虚类AbstractExecutorService,实现ExecutorService接口。实现ExecutorService相关接口。
ThreadPoolExecutor类,继承虚类AbstractExecutorService。实现初始化线程池数量、策略并执行线程。
ScheduledThreadPoolExecutor类,继承ThreadPoolExecutor类并实现ScheduledExecutorService接口。实现计划执行相关接口。
执行类,定义ThreadPoolExecutor和ScheduledThreadPoolExecutor类,并使用相关concurrent类方法。
二.简述下从定义线程池,到其底层执行的简单流程
ExecutorService executorService = Executors.newFixedThreadPool(3); executorService.submit(new NewTask());
简单定义了如上两句代码,JDK自动创建3个固定大小的线程的线程池,submit实现了Runnable接口的NewTask对象以后,JDK自动启动线程并执行NewTask对象的run方法。流程是如何的呢?
1.Executors的newFixedThreadPool方法new了一个ThreadPoolExecutor对象,且new了一个LinkedBlockingQueue对象。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
2.调用ThreadPoolExecutor的构造函数,其中ThreadFactory默认使用defaultThreadFactory,defaultHandler为AbortPolicy。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
3.初始化以后,调用AbstractExecutorService类的submit方法,执行Runnable对象。
public Future> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFutureftask = newTaskFor(task, null); execute(ftask); return ftask; }
4.RunnableAdapter实现了Callable接口,FutureTask类包含callable类成员对象。
FutureTask实现RunnableFuture接口,RunnableFuture继承Runnable接口。所以newTaskFor(task, null)方法返回一个FutureTask对象。
public class FutureTaskimplements RunnableFuture public interface RunnableFuture extends Runnable, Future RunnableFuture ftask = newTaskFor(task, null); protected RunnableFuture newTaskFor(Runnable runnable, T value) { return new FutureTask (runnable, value); } public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable } public static Callable callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter (task, result); } static final class RunnableAdapter implements Callable { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }
5.关键的调用ThreadPoolExecutor类execute方法,管理线程池并执行Runnable任务。主要逻辑如下:
1)如果线程数量小于corePoolSize,新来一个任务,创建一个新线程。
2)如果线程数量等于corePoolSize,则将任务缓存到workQueue中。
3)如果线程数量等于corePoolSize并且workQueue队列已满,则继续创建线程直到等于maximumPoolSize。
4)如果线程数量等于maximumPoolSize,且workQueue队列已满,则根据defaultHandler策略执行相应措施。默认是AbortPolicy,抛出一个运行时异常RejectedExecutionException。另外还有3种策略:CallerRunsPolicy->如果线程池没有shutdown,则直接调用Runnable的run方法执行。如果线程池shutdown,则直接丢弃;DiscardPolicy->直接丢弃,没有任何异常;DiscardOldestPolicy->丢弃最老的任务,并调用线程池的execute方法执行,如果线程池没有shutdown。
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69881.html
摘要:整个包,按照功能可以大致划分如下锁框架原子类框架同步器框架集合框架执行器框架本系列将按上述顺序分析,分析所基于的源码为。后,根据一系列常见的多线程设计模式,设计了并发包,其中包下提供了一系列基础的锁工具,用以对等进行补充增强。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首发于一世流云专栏:https...
摘要:是目前的实验收集器。也是需要暂停程序一切的工作,然后多线程执行垃圾回收。与最大的不同,它关注的是垃圾回收的吞吐量。这里的吞吐量指的是总时间与垃圾回收时间的比例。筛选回收,评估标记垃圾,根据模式回收垃圾。 《对象搜索算法与回收算法》介绍了垃圾回收的基础算法,相当于垃圾回收的方法论。接下来就详细看看垃圾回收的具体实现。 上文提到过现代的商用虚拟机的都是采用分代收集的,不同的区域用不同的收集...
摘要:本文主要内容为简单总结中线程池的相关信息。方法簇方法簇用于创建固定线程数的线程池。三种常见线程池的对比上文总结了工具类创建常见线程池的方法,现对三种线程池区别进行比较。 概述 线程可认为是操作系统可调度的最小的程序执行序列,一般作为进程的组成部分,同一进程中多个线程可共享该进程的资源(如内存等)。在单核处理器架构下,操作系统一般使用分时的方式实现多线程;在多核处理器架构下,多个线程能够...
摘要:为程序员金三银四精心挑选的余道面试题与答案,欢迎大家向我推荐你在面试过程中遇到的问题我会把大家推荐的问题添加到下面的常用面试题清单中供大家参考。 为Java程序员金三银四精心挑选的300余道Java面试题与答案,欢迎大家向我推荐你在面试过程中遇到的问题,我会把大家推荐的问题添加到下面的常用面试题清单中供大家参考。 前两天写的以下博客,大家比较认可,热度不错,希望可以帮到准备或者正在参加...
摘要:下面是线程相关的热门面试题,你可以用它来好好准备面试。线程安全问题都是由全局变量及静态变量引起的。持有自旋锁的线程在之前应该释放自旋锁以便其它线程可以获得自旋锁。 最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案。 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员...
阅读 2003·2019-08-30 15:52
阅读 2949·2019-08-29 16:09
阅读 1304·2019-08-28 18:30
阅读 2437·2019-08-26 12:24
阅读 1026·2019-08-26 12:12
阅读 2256·2019-08-26 10:45
阅读 554·2019-08-23 17:52
阅读 758·2019-08-23 16:03