ThreadPoolExecutor添加线程是通过 execute(Runnable command),此方法代码行数不多,但是由于太精炼了,不大好读懂,理解完之后,特写下笔记加深印象.
一句话解释:
如果BlockingQueue没有大小限制,如果在执行的线程个数小于corePoolSize,则自动执行,否则当前线程存入BlockingQueue.
备注:如果BlockingQueue有限制,超出的线程要么拒绝,要么抢跑直接执行(需要当前线程个数没有超过maximumPoolSize).
下面是具体的代码,已经添加注释,如果有问题欢迎大家指出.
//ThreadPoolExecutor public void execute(Runnable command) { if (command == null) throw new NullPointerException(); //--如果核心线程已经用尽( poolSize >= corePoolSize ), 进入if分支 //--核心线程没用完,立即执行线程,不进入if分支(!addIfUnderCorePoolSize(command)) if (poolSize >= corePoolSize /*核心线程没空余*/ || !addIfUnderCorePoolSize(command)/*核心线程有空余*/) { //--如果核心线程已经用尽, 并且runState == RUNNING, 则添加command到workQueue中去 if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) //如果线程池状态不为RUNNING,或者正在工作的线程个数为0,则尽量保证添加的Command被处理(Reject) ensureQueuedTaskHandled(command); } //--如果workQueue已满,则尝试直接执行线程(需要保证当前运行线程<maximumPoolSize,感觉好像插队了一样,不公平) else if (!addIfUnderMaximumPoolSize(command)) //如果poolSize>=maximumPoolSize,则拒绝(通过抛出运行时异常) reject(command); // is shutdown or saturated } }
几点注意
- workers中存放的是 正在执行的线程,当执行完毕,并且BlockingQueue中无数据时,线程会会自动从workers中删除 (通过Worker.workerDone(this))
- workQueue中存放的是 由于corePoolSize限制,来不及执行的线程.如果由于workQueue的限制导致存放不下的,有可能抢跑而直接执行(前提是线程数量小于maximumPoolSize,否则直接拒绝).
- ThreadPoolExecutor 构造函数中有2个限制:一个是核心线程数量,一个是最大线程数量. 上面函数不好理解是因为有一个可能潜在的限制,就是缓存队列(BlockingQueue)的大小限制.
- 放入BlockingQueue中的线程何时执行: 每一个Worker初始化之后,会立即去执行,但是当执行完成之后即会尝试从BlockingQueue中取线程执行.下面是对应代码.
//Worker public void run() { try { Runnable task = firstTask; firstTask = null; //task = getTask()就是尝试从队列中取线程来执行 while (task != null || (task = getTask()) != null) { runTask(task); task = null; } } finally { workerDone(this); } }
相关推荐
ThreadPoolExecutor源码解析.pdf
ThreadPoolExecutor源码解析.md
线程池原理-ThreadPoolExecutor源码解析 1.构造方法及参数 2.阻塞对列: BlockingQueue 3.线程工厂: DefaultThreadFactory 4.拒绝策略: RejectedExecutionHandler 5.执行线程 Executor
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了...
线程池ThreadPoolExecutor底层原理源码分析
1.资源简介:PyQt5中使用多线程模块QThread解决了PyQt5界面程序执行比较耗时操作时,程序卡顿出现的无响应以及界面输出无法实时显示的问题,采用线程池ThreadPoolExecutor解决了ping多个IP多任务耗时问题。...
11-线程池 ThreadPoolExecutor 底层原理源码分析(上)-周瑜.pdf 12-线程池 ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf 13、线程池 ForkJoinPool实战及其工作原理分析 (1).pdf 14、深入理解井发可见性、...
11-线程池 ThreadPoolExecutor 底层原理源码分析(上)-周瑜.pdf 12-线程池 ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf 13、线程池 ForkJoinPool实战及其工作原理分析 (1).pdf 14、深入理解井发可见性、...
Java,线程池,ThreadPoolExecutor
ThreadPoolExecutor线程池,有详尽介绍,本人进行过测试,可以使用
线程池的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,那么超出数量的线程排队等候,等其他线程执行完毕再从队列中取出任务来执行。...
如果你打算自己手动配置和调整ThreadPoolExecutor类时,建议先阅读一下下面的注意事项:Core and maximum pool sizesA T
ThreadPoolExecutor使用和思考
1. 任务提交到线程池中,首先会检测线程池中核心线程数是否已经到达到达上限,若未到达则执行步骤2,反之执行步 2. 初始化一条线程执行任务 3. 尝试将任务放到
线程池执行器 使用多线程ThreadPoolExecutor从Web加载图像
于是乎到现在的Hibernate、MyBatis、Spring、Spring MVC、AQS、ThreadPoolExecutor、CountDownLatch使用场景和核心源码分析。 感觉自己还是真的菜鸡,有太多框架的底层实现都不怎么了解。 当山头被一座一座攻克时,...
相比 threading 等模块,该模块通过 submit 返回的是一个 future 对象,它是一个未来可期的对象,通过它可以获悉线程的状态主线程(或进程)中可以获取某一个线程(进程)执行的状态或者某一个任务执行的状态及返回值: ...
因为asyncio程序中的每个线程都有自己的事件循环,但它只会在主线程中为你自动创建一个事件循环。所以如果你asyncio.get_event_loop在主线程中调用一次,它将自动创建一个循环对象并将其设置为默认值,但是如果你在...
(转)线程池:java_util_ThreadPoolExecutor 比较详细的介绍了ThreadPoolExecutor用法与属性
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long