大家先从ThreadPoolExecutor的总体流程入手:
针对ThreadPoolExecutor代码,我们来看下execute方法:
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); //poolSize大于等于corePoolSize时不增加线程,反之新初始化线程 if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { //线程执行状态外为执行,同时可以添加到队列中 if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } //poolSize大于等于corePoolSize时,新初始化线程 else if (!addIfUnderMaximumPoolSize(command)) //无法添加初始化执行线程,怎么执行reject操作(调用RejectedExecutionHandler) reject(command); // is shutdown or saturated } }
我们再看下真正的线程执行者(Worker):
private final class Worker implements Runnable { /** * Runs a single task between before/after methods. */ private void runTask(Runnable task) { final ReentrantLock runLock = this.runLock; runLock.lock(); try { /* * If pool is stopping ensure thread is interrupted; * if not, ensure thread is not interrupted. This requires * a double-check of state in case the interrupt was * cleared concurrently with a shutdownNow -- if so, * the interrupt is re-enabled. */ //当线程池的执行状态为关闭等,则执行当前线程的interrupt()操作 if ((runState >= STOP || (Thread.interrupted() && runState >= STOP)) && hasRun) thread.interrupt(); /* * Track execution state to ensure that afterExecute * is called only if task completed or threw * exception. Otherwise, the caught runtime exception * will have been thrown by afterExecute itself, in * which case we don't want to call it again. */ boolean ran = false; beforeExecute(thread, task); try { //任务执行 task.run(); ran = true; afterExecute(task, null); ++completedTasks; } catch (RuntimeException ex) { if (!ran) afterExecute(task, ex); throw ex; } } finally { runLock.unlock(); } } /** * Main run loop */ public void run() { try { hasRun = true; Runnable task = firstTask; firstTask = null; //判断是否存在需要执行的任务 while (task != null || (task = getTask()) != null) { runTask(task); task = null; } } finally { //如果没有,则将工作线程移除,当poolSize为0是则尝试关闭线程池 workerDone(this); } } } /* Utilities for worker thread control */ /** * Gets the next task for a worker thread to run. The general * approach is similar to execute() in that worker threads trying * to get a task to run do so on the basis of prevailing state * accessed outside of locks. This may cause them to choose the * "wrong" action, such as trying to exit because no tasks * appear to be available, or entering a take when the pool is in * the process of being shut down. These potential problems are * countered by (1) rechecking pool state (in workerCanExit) * before giving up, and (2) interrupting other workers upon * shutdown, so they can recheck state. All other user-based state * changes (to allowCoreThreadTimeOut etc) are OK even when * performed asynchronously wrt getTask. * * @return the task */ Runnable getTask() { for (;;) { try { int state = runState; if (state > SHUTDOWN) return null; Runnable r; if (state == SHUTDOWN) // Help drain queue r = workQueue.poll(); //当线程池大于corePoolSize,同时,存在执行超时时间,则等待相应时间,拿出队列中的线程 else if (poolSize > corePoolSize || allowCoreThreadTimeOut) r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS); else //阻塞等待队列中可以取到新线程 r = workQueue.take(); if (r != null) return r; //判断线程池运行状态,如果大于corePoolSize,或者线程队列为空,也或者线程池为终止的工作线程可以销毁 if (workerCanExit()) { if (runState >= SHUTDOWN) // Wake up others interruptIdleWorkers(); return null; } // Else retry } catch (InterruptedException ie) { // On interruption, re-check runState } } } /** * Performs bookkeeping for an exiting worker thread. * @param w the worker */ //记录执行任务数量,将工作线程移除,当poolSize为0是则尝试关闭线程池 void workerDone(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); if (--poolSize == 0) tryTerminate(); } finally { mainLock.unlock(); } }
通过上述代码,总结下四个关键字的用法
- corePoolSize 核心线程数量
线程保有量,线程池总永久保存执行线程的数量
- maximumPoolSize 最大线程数量
最大线程量,线程最多不能超过此属性设置的数量,当大于线程保有量后,会新启动线程来满足线程执行。
- 线程存活时间
获取队列中任务的超时时间,当阈值时间内无法获取线程,则会销毁处理线程,前提是线程数量在corePoolSize 以上
- 执行队列
执行队列是针对任务的缓存,任务在提交至线程池时,都会压入到执行队列中。所以这里大家最好设置下队列的上限,防止溢出
ThreadPoolExecuter的几种实现
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
- CachedThreadPool 执行线程不固定,
相关推荐
Java线程池ThreadPoolExecutor原理及使用实例 Java线程池ThreadPoolExecutor是Java并发编程中的一种基本机制,主要用于管理和执行任务的线程池。下面对其原理和使用实例进行详细介绍。 线程池概述 线程池是一个...
线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor...
* 降低了系统的开销:ThreadPoolExecutor 可以重复使用线程,避免了频繁创建和销毁线程的开销。 * 提高了系统的灵活性:ThreadPoolExecutor 可以根据不同的工作负载动态地调整线程池的大小。 ThreadPoolExecutor 的...
### 线程池 `ThreadPoolExecutor` 原理源码分析 #### 一、概述 线程池作为 Java 并发编程中的重要组件,在实际应用中被广泛使用。其核心类 `ThreadPoolExecutor` 实现了对线程的管理、调度等功能。本文将围绕 `...
线程池ThreadPoolExecutor底层原理源码分析
"java 中ThreadPoolExecutor 原理分析" ThreadPoolExecutor 是 Java 并发编程中的一种高级线程池实现,它提供了一个灵活的线程池管理机制,允许开发者根据需要配置线程池的参数以满足不同的需求。在这篇文章中,...
线程池原理-ThreadPoolExecutor源码解析 1.构造方法及参数 2.阻塞对列: BlockingQueue 3.线程工厂: DefaultThreadFactory 4.拒绝策略: RejectedExecutionHandler 5.执行线程 Executor
线程池ThreadPoolExecutor实战及其原理分析(上)
创建线程池使用`ThreadPoolExecutor`构造函数,其参数含义如下: - `corePoolSize`: 核心线程数,表示线程池中保持的最小线程数。 - `maximumPoolSize`: 最大线程数,定义了线程池允许的最大并发线程数。 - `...
根据提供的文件信息,我们可以深入探讨线程池`ThreadPoolExecutor`的工作原理及其实现细节,同时也会涉及并发编程中的一些关键概念和技术。 ### 线程池`ThreadPoolExecutor`概述 `ThreadPoolExecutor`是Java中非常...
根据给定文件的信息,我们可以深入探讨Java中`ThreadPoolExecutor`线程池的底层实现原理,特别是其核心数据结构`ctl`以及线程池的各种状态转换。以下是对这些知识点的详细解释: ### 一、线程池`ThreadPoolExecutor...
本文将详细讲解如何使用Java中的`ThreadPoolExecutor`来抓取论坛帖子列表,结合源码分析和实用工具的应用。 首先,我们要了解线程池的基本原理。线程池是由一组预先创建的线程组成的,这些线程可以复用,而不是每次...
ThreadPoolExecutor线程池原理及其execute方法详解 ThreadPoolExecutor是Java并发包中提供的线程池类,用于管理和执行异步任务。ThreadPoolExecutor的执行原理可以分为四个步骤: 1.核心线程池:...
总结来说,Java调度原理涉及线程创建、优先级、调度策略等多个方面,开发者需要根据具体需求选择合适的调度方式,并合理使用并发工具,以实现高效、稳定的多线程程序。在实际应用中,要时刻注意线程安全,避免死锁、...
本文将深入解析ThreadPoolExecutor的execute()方法执行流程,以帮助我们理解线程池的工作原理。 当一个任务被提交到线程池,线程池的执行策略主要分为四步: 1. 首先,线程池会检查当前的核心线程数是否已达到设定...
本文将详细介绍线程池的实现原理、线程池的优势、线程池的类型、线程池的创建方式以及线程池的使用注意事项。 一、线程池的实现原理 线程池的实现原理基于池化技术,即减少每次获取资源的消耗,提高资源利用率。...
2. 线程池(ThreadPoolExecutor)的概念与优势: 线程池是一种多线程处理形式,它预先创建了若干数量的可执行线程并放在一个池子中,需要的时候直接拿来使用,使用完毕后再放回池中。线程池技术的优势在于:能够减少...
在Android系统原理及开发要点详解系列的第四部分中,我们将深入探讨Android系统的内核、运行机制、组件交互以及开发者需要注意的关键点。这一部分是整个系列的总结,旨在为Android开发者提供一个全面的理解,以便...
11-线程池 ThreadPoolExecutor 底层原理源码分析(上)-周瑜.pdf 12-线程池 ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf 13、线程池 ForkJoinPool实战及其工作原理分析 (1).pdf 14、深入理解井发可见性、...
11-线程池 ThreadPoolExecutor 底层原理源码分析(上)-周瑜.pdf 12-线程池 ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf 13、线程池 ForkJoinPool实战及其工作原理分析 (1).pdf 14、深入理解井发可见性、...