关于问题JAVA 架构之线程池是怎样工作的?一共有 4 位热心网友为你解答:
【1】、来自网友【梦幻勇敢的春风】的最佳回答:
谢谢邀请!下面介绍一下线程池是怎样工作的?
ThreadPoolExecutor 的类关系如下:
-
Executor 是一个接口,它是 Executor 框架的基础,它将任务的提交与任务的执行分离开来。
-
ExecutorService 接口继承了 Executor,在其上做了一些 shutdown()、submit()的扩展,可以说是真正的线程池接口;
-
AbstractExecutorService 抽象类实现了 ExecutorService 接口中的大部分方法;
-
threadPoolExecutor 是线程池的核心实现类,用来执行被提交的任务。
-
ScheduledExecutorService 接口继承了 ExecutorService 接口,提供了带”周期执行”功能 ExecutorService;
-
ScheduledThreadPoolExecutor 是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor 比 Timer 更灵活,功能更强大。
定义线程池
线程池的创建各个参数含义 及流程 如下:
1、corePoolSize
① 线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于 corePoolSize;
② 如果当前线程数为 corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
③ 如果执行了线程池的 prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
2、maximumPoolSize
线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,
则创建新的线程执行任务,前提是当前线程数小于 maximumPoolSize
3、keepAliveTime
线程空闲的存活时间,即当线程没有任务执行时,继续存活的时间。
默认情况下,该参数只在线程数大于 corePoolSize 时才有用。
4、TimeUnit
keepAliveTime 的时间单位。
5、WorkQueue
用于保存等待执行的任务的阻塞队列,一般来说,我们应该尽量使用有界队列,因为使用无界队列作为工作队列会对线程池做如下影响。
① 当线程池中的线程数达到 corePoolSize 后,新任务将在无界队列中等待,因此线程池中的线程数不会超过 corePoolSize。
② 由于 1,使用无界队列时 maximumPoolSize 将是一个无效参数。
③ 由于 1 和 2,使用无界队列时 keepAliveTime 将是一个无效参数。
④ 更重要的,使用无界 queue 可能会耗尽系统资源,有界队列则有助于防止资源耗尽,同时即使使用有界队列,也要尽量控制队列的大小在一个合适的范围。
所以我们一般会使用,ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue。
6、threadfactory
创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名,
当然还可以更加自由的对线程做更多的设置,比如设置所有的线程为守护线程。
Executors 静态工厂里默认的 threadfactory,线程的命令 规则时”pool-数字-thread-数字”
7、RejectedExecutionHandler 拒绝策略
线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了 4 种策略:
① AbortPolicy : 直接抛出异常,默认策略
② CallerRunsPolicy: 用调用者所在的线程来执行任务
③ DiscardOldestPolicy : 丢弃阻塞队列中靠最前的任务,并执行当前任务
④ Discardpolicy : 直接丢弃任务
当然也可以根据应用场景实现 RejectedExecutionHandler 接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
线程池的工作机制
① 如果当前运行的线程 少于 corePoolSize,则创建新线程来执行任务
② 如果运行的线程等于或多于 corePoolSize,则将任务加入 BlockingQueue
③ 如果无法将任务加入 BlockingQueue(队列已满),则创建新的线程来处理任务。
④ 如果创建新线程将使当前运行的线程超出 maximumPoolSize,任务将被拒绝,
并调用 RejectedExecutionHandler.rejectedExecution()方法。
【2】、来自网友【Java 技术栈】的最佳回答:
java.util.concurrent 包中我们能找到线程池的定义,其中 ThreadPoolExecutor 是我们线程池核心类,首先看看线程池类的主要参数有哪些。
corePoolSize:线程池的核心大小,也可以理解为最小的线程池大小。
maximumPoolSize:最大线程池大小。
keepAliveTime:空余线程存活时间,指的是超过 corePoolSize 的空余线程达到多长时间才进行销毁。
unit:销毁时间单位。
workQueue:存储等待执行线程的工作队列。
threadFactory:创建线程的工厂,一般用默认即可。
handler:拒绝策略,当工作队列、线程池全已满时如何拒绝新任务,默认抛出异常。
线程池工作流程
1、如果线程池中的线程小于 corePoolSize 时就会创建新线程直接执行任务。
2、如果线程池中的线程大于 corePoolSize 时就会暂时把任务存储到工作队列 workQueue 中等待执行。
3、如果工作队列 workQueue 也满时:当线程数小于最大线程池数 maximumPoolSize 时就会创建新线程来处理,而线程数大于等于最大线程池数 maximumPoolSize 时就会执行拒绝策略。
【3】、来自网友【乐淘学编程】的最佳回答:
通俗易懂的给你解释一下,池塘里有很多鱼,我们捞一条上来把玩一番,把玩一段时间后放回池塘里去。这就是线程池的工作原理,只不过这个池塘里放的不是鱼,是一个个线程对象,用到一个就拿一个,用完放回池塘内,而这个池塘在计算机内就是对应在软件的内存中了。
【4】、来自网友【小光童鞋】的最佳回答:
ThreadPool 工作原理任务先去核心线程池,如果核心线程池没有则存入到 Q 中;Q 满了去启新的线程(启新线程时会全局锁),不能启的话就返回错误需要多了解些,参数配置和使用结合。
以上就是关于问题【JAVA 架构之线程池是怎样工作的?】的全部回答,希望能对大家有所帮助,内容收集于网络仅供参考,如要实行请慎重,任何后果与本站无关!