- 浏览: 64264 次
- 性别:
- 来自: 成都
-
文章分类
最新评论
简单介绍一下java Executors框架来管理线程池原理:
1、线程池中的线程如何创建?创建后保存在哪里?
线程池中的每个线程封装在workder中,然后保存在一个HashMap<Workder>中。
2、当任务多于线程的时候怎么执行?例如有5个任务但是只有只创建了3个线程。
看Worker中的run方法调用的是runWorker方法:
很显然这是生产者消费者模式的体现。runWorker循环阻塞等待从workQueue中取出任务。然后执行。
总结线程池原理:
线程池在执行线程的时候创建线程。然后执行完的线程并没有立即销毁而是阻塞等待 workQueue中来新任务然后接着执行。线程池也是生产者消费者模式的体现。
//创建一个线程数大小为3的线程池 Executors.newFixedThreadPool(3);
1、线程池中的线程如何创建?创建后保存在哪里?
public class ThreadPoolExecutor extends AbstractExecutorService { //用队列保存需要执行的任务 private final BlockingQueue<Runnable> workQueue; //将Worker保存在HashSet中,Worker是什么? private final HashSet<Worker> workers = new HashSet<Worker>(); //Worker包装了Runnable private final class Worker extends AbstractQueuedSynchronizer implements Runnable { private static final long serialVersionUID = 6138294804551838833L; Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } public void run() { runWorker(this); } //看execute方法 public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { //重点来了,addWorker.好了这就是线程保存在哪里。 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); } //addWorker源码 private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { final ReentrantLock mainLock = this.mainLock; w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { mainLock.lock(); try { int c = ctl.get(); int rs = runStateOf(c); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); //保存线程 workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { //运行该线程 t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
线程池中的每个线程封装在workder中,然后保存在一个HashMap<Workder>中。
2、当任务多于线程的时候怎么执行?例如有5个任务但是只有只创建了3个线程。
看Worker中的run方法调用的是runWorker方法:
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { //循环获取Runnable,getTask()方法从workQueue中获取任务 while (task != null || (task = getTask()) != null) { w.lock(); if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }
很显然这是生产者消费者模式的体现。runWorker循环阻塞等待从workQueue中取出任务。然后执行。
总结线程池原理:
线程池在执行线程的时候创建线程。然后执行完的线程并没有立即销毁而是阻塞等待 workQueue中来新任务然后接着执行。线程池也是生产者消费者模式的体现。
发表评论
-
读ThreadLocal源代码
2017-10-12 15:00 244//可以存取线程局部变量 //先看构造函数 pub ... -
读Exchanger源码
2017-10-10 11:38 341//用于线程间交换数据 public V exchang ... -
读Executors源码
2017-09-29 15:23 269//一个管理线程创建的类里面都是静态方法 //创建一 ... -
读ScheduledThreadPoolExecutor源码
2017-09-25 17:33 436//一个可以延迟执行的定时任务 //先看构造函数 构造函 ... -
读部分ThreadPoolExecutor源码
2017-09-25 15:27 312//线程池 //先看构造方法 public Threa ... -
读AbstractExecutorService
2017-09-23 16:34 337//他是ExecutorService的部分实现 pub ... -
读ExecutorCompletionService源码
2017-09-23 11:22 493//一个用来管理已完成任务的service,内部封装了一个 ... -
读FutureTask源码
2017-09-22 16:45 276//一个可以异步返回计算的结果 //它同时实现了Futu ... -
读ConcurrentSkipListMap源码
2017-09-21 15:11 304//数据结构是跳表 关于数据结构http://blog.c ... -
读Semaphore源码
2017-09-09 14:58 301//一个信号量,只有在池中还拥有许可时才允许线程继续执行。 ... -
读CyclicBarrier源码
2017-09-01 17:59 359//一个循环的屏障。所有的线程在屏障处等待其他线程执行完毕 ... -
读CountDownLatch源码
2017-09-01 14:01 331//在完成一组操作之前允许一个或多个线程等待内部用的AQS ... -
读ConcurrentLinkedQueue
2017-09-01 11:40 300//这是一个无阻塞的队列没有加任何锁全部利用CAS机制实现 ... -
读ConcurrentHashMap源码
2017-08-31 11:21 284//先看构造函数 public ConcurrentHa ... -
读CopyOnWriteArrayList源码
2017-08-22 12:59 415//在该集合上的写操作都是在原有的副本上进行的操作。这样可 ... -
读LinkedBlockingDeque源码
2017-08-21 14:26 570//这是一个支持双端操作的可阻塞队列 //先看构造函数 ... -
读SynchronousQueue源码
2017-08-10 10:51 379//先看构造方法 public SynchronousQ ... -
读PriorityBlocking源码
2017-08-09 13:47 357//一个基于而为堆的优先级队列,它是无界的。 //先看构 ... -
读DelayQueen源码
2017-08-07 15:16 281//一个基于二叉堆优先 ... -
LinkedblockingQueue源码解读
2017-08-04 13:03 353//LinkedBlockQueue //先看构造函数 ...
相关推荐
西工大数据结构实验
操作系统学习
weixin046云上考场+ssm(文档+源码)_kaic
基于C语言+STM32+MQTT协议实现的物联网健康监测系统(底层)+微信小程序操作界面+源码+项目文档+模块接线说明,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C语言+STM32+MQTT协议实现的物联网健康监测系统(底层)+微信小程序操作界面+源码+项目文档+模块接线说明,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档~ 基于C语言+STM32+MQTT协议实现的物联网健康监测系统(底层)+微信小程序操作界面+源码+项目文档+模块接线说明,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C语言+STM32+MQTT协议实现的物联网健康监测系统(底层)+微信小程序操作界面+源码+项目文档+模块接线说明,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档
刘铭-计算机视觉-简历-算法OCR.md
数据结构学习
我的图书馆特色藏书推荐
前端分析-2023071100789s10
2025年Go语言教程核心内容指南
数据结构学习
2025年美赛全流程指南
操作系统学习
内容概要:本文档详细介绍了如何编制一份详尽的详细设计说明书,主要面向J2EE开发环境。文中具体覆盖了项目设计的关键要素,比如多项目的管理和组织方法、各系统层次及其内部模块的组成与关系解析,源码及各类设计规则的说明,以及对界面、数据库、异常处理等方面的要求。此外,文档还特别提供了详细的业务功能设计指南,涵盖界面原型设计、交互路径、数据校验、日志处理等环节的细致规定。同时强调了编码规范和标签一致性对项目稳定性和高效维护的重要性。 适用人群:本文档是给参与复杂J2EE项目的程序员、项目经理和其他相关人员作为编写详细设计方案的基础材料和技术指引。它适用于拥有一定的编程知识并熟悉Java及相关Web技术框架的开发者。 使用场景及目标:旨在提高项目团队协作效率的同时确保整个项目的一致性与可靠性。通过提供标准化的方法论支持,帮助开发者完成从架构规划直至具体实现阶段的所有任务。最终目的是构建高质量且容易扩展的应用系统。 其他说明:为了更好地服务于实际应用的需求,该模板鼓励各团队在遵循基本结构的基础上,依据自身特性灵活调整文档的具体构成要素,并积极借鉴过往优秀案例的经验教训以改进和完善现有的设计流程。
数据结构学习
后端面试常见问题总结 - JAVA基础.pdf
该资源包可以生成节点标签表格,同时直接提取odb文件当中的节点对应信息
数据结构学习
本研究借助 ABAQUS 软件深入探究两个金属部件的摩擦磨损过程,全面阐述了从模型构建到结果剖析的完整流程,并结合刹车片与刹车盘的实际案例展现其应用。通过详细的图文及表格说明,为相关工程领域的材料磨损分析与部件设计优化提供了直观且有力的参考,有助于提升设备性能与可靠性,降低研发成本。
人工智能资源,C语言 实现识别手写数字,读取指定名称的图像文件,将图像的前 28x28 个像素转换为归一化的灰度值,并将这些灰度值存储到传入的双精度浮点数数组中。
泉盛TG-200对讲机中文写频软件改频率软件V1.0.0.8