线程池工作原理

线程管理当线程执行完当前任务时,它不会死亡,而是会从队列中取1,以减少系统资源消耗。
通过复用现有线程,减少了创建和销毁线程带来的消耗。
2.提高响应速度。
当任务到达时,可以立即执行,无需等待新线程创建。
3.提高管理线程的能力。
线程是稀缺资源,如果不加限制地创建,不仅会消耗大量的系统资源,还会降低系统的稳定性。
线程池可用于统一分配、调优和监控线程。
本文主要关注ThreadPoolExecutor创建方法(线程池框架的核心类)的参数:1.corePoolSize线程池的核心线程数量。
当任务提交时,线程池会创建一个新的线程来执行该任务,直到当前线程数等于corePoolSize,如果当前线程数为corePoolSize,则继续提交的任务将被保存在阻塞中。
排队并等待执行。
2.maximumPoolSize附加线程的最大数量。
前面说过,任务数量充足,使用有限的队列。
如果当前阻塞队列已满,继续发送任务,则会创建一个新的线程先执行队列中的任务,如果队列中的消息执行完毕,多余的线程会在一定时间后自动销毁。
时间。
3.keepAliveTime是线程空闲时的生存时间。
默认情况下,可以理解为最大附加线程数没有任何工作可做。
如果线程的额外空闲时间达到keepAliveTime,就会过期,直到线程池中的线程数不超过corePoolSize。
但如果调用allowCoreThreadTimeOut(boolean)方法,keepAliveTime参数也会起作用,直到线程池中的线程数变为0。
4、UnitkeepAliveTime参数的时间单位。
5.workQueue任务缓存队列,用于存储等待执行的任务。
如果当前线程数为corePoolSize,则继续提交的任务会保存在任务缓存队列中,等待执行。
一般来说,这里的BlockingQueue有以下三个选项:*SynchronousQueue:阻塞队列不存储元素,每次插入操作必须等待另一个线程调用remove操作,否则会被阻塞插入过程是永久性的。
因此,如果线程池中绝对没有空闲线程(任务平均提交速度快于处理速度),则可能会出现无限线程增长。
*LinkedBlockingQueue:基于链表结构的阻塞队列,如果不设置初始容量,其容量将为Integer.MAX_VALUE,是一个无限队列。
因此,如果线程池中的线程数量达到corePoolSize并且没有空闲线程(平均任务提交速度快于处理速度),任务缓存队列可能会无限增长。
*ArrayBlockingQueue:基于数组结构的有限阻塞队列,按FIFO排序任务。
6.threadFactory线程工厂,创建新线程时使用的线程工厂。
7.处理器任务拒绝策略。
当阻塞队列已满且线程池中的线程数达到PoolSize最大大小时,如果继续提交任务,将采用任务拒绝策略来处理该任务任务拒绝策略:*AbortPolicy:忽略任务并抛出RejectedExecutionException异常,默认策略;*CallerRunsPolicy:任务由调用execute方法的线程执行;*DiscardPolicy:丢弃任务,但不抛出异常;*DiscardOldestPolicy:丢弃阻塞队列的前台任务,然后再次尝试该任务(重复此过程)。
*当然,你也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,比如对无法处理的任务进行日志记录或持久化存储。
总结一下resume参数:假设corePoolSize为10,maximumPoolSize为10,线程空闲时的停留时间为60秒,队列使用有限队列ArrayBlockingQueue设置最小值为200,使用拒绝策略,当前任务提交进程为2000个任务数如下:当前2000个任务进来,10个核心线程处理,剩余的1990个任务排队等待200。
还剩下1790个任务。
当队列满时,将创建10个附加线程,与主线程一起执行剩余的1780个任务。
当仍有任务无法处理时,将触发任务拒绝策略。
   目前,有220个任务进来,10个核心线程处理它们,210个任务中剩余的200个正在排队。
剩下10个任务。
当队列满时,会额外创建10个线程执行队列中无法容纳的任务。
当附加线程和主线程完成处理队列内的队列时。
当没有任务执行时,额外的线程会等待我们设置的KeepAliveTime,或者没有任务则被回收。
以上是绝对理想的情况。
从参数可以看出,主线程和辅助线程的值是相同的,辅助线程的回收时间为0,并且使用无限队列。
默认拒绝策略是AbortPolicy。
如果主线程和附加线程无法处理这种情况,它们将继续对任务进行排队。
可能出现的问题:队列太大,当任务大小足够大超过队列时,导致内存溢出和OOM。
处理其他主题。
将创建太多线程。
可能存在的问题:特殊场景下,线程过多可能会导致系统崩溃。
CPU负载过高。
1、具体方案根据业务系统而定:华睿批量验证示例:定时任务CZJZRW001每2分钟轮询一次,验证任务的待处理和运行状态会在议程中查询到调度中,进入异步反欺诈验证、付款验证、充值验证、贷款验证。
选定的验证根据处理结果更新任务验证表的验证状态。
已处理成功或失败的计划任务无法再次轮询。
这样就不需要考虑上面的场景了。
如果使用线程池,如果主线程无法处理额外的线程并且队列已满,则使用DiscardPolicy拒绝并且不抛出异常来满足这种业务场景。
类结构如图2所示。
思路可以是实现RejectedExecutionHandler接口来自定义拒绝策略,将被拒绝的任务信息暂时存储到磁盘,等到线程池负载变低时从磁盘读取并重新提交给执行的任务。

什么是java线程池

多线程就是合理分配计算机资源,创建不同的线程来处理不同的任务。
然而,计算机创建或销毁线程的成本也相对较高。
有时我们需要同时处理很多事情,我们经常需要创建和销毁线程,这需要花费大量的时间。
为了解决这个问题,我们可以借助线程池的概念。
所谓线程池就是用来集中管理线程的。
当需要线程的时候,可以从线程池中取出空闲的线程,这样可以减少线程的频繁创建和销毁,节省大量的时间,减少很多不必要的操作。
Java中提供了ThreadPoolExecutor类用于线程管理。
该类继承自AbstractExecutorService,AbstractExecutorService实现了ExecutorService接口。
我们可以使用ThreadPoolExecutor来创建线程池。
ThreadPoolExecutor的构造方法中有几个参数,可以配置各种参数进行优化。
该类的源码构造方法为:publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueueworkQueue,ThreadFactorythread(Factory,RejectedExecutionHandlerhandler)各个参数的含义为corePoolSize:线程池中核心线程的数量,如果当前数量中的线程数线程池小于这个配置,即使有新任务到来,即使线程池中还有线程,如果有空闲线程,程序会继续创建新线程,并将MaximumPoolSize放入线程池中:线程池中最大线程数keepAliveTime:当线程池中线程数大于配置的核心线程数(corePoolSize)时,如果当前空闲线程存在,可能有空闲线程的时间如果在keepAliveTime时间内没有新的任务,则使用此行但是,如果配置了allowCoreThreadTimeOut=true,那么如果空闲时间超过“keepAliveTime”,线程即使终止也会一直存在于线程池中。
Unit:空闲线程的连接时间(keepAliveTime)的时间单位workQueue:阻塞任务队列,用于存储等待执行的任务。
threadFactory:线程工厂允许您根据需要创建线程对象,并设置线程名称、优先级等属性信息。
Handler:如果线程池中的线程数超过指定的最大值,则新任务将被拒绝。
您可以自己定义拒绝策略。
如果新任务被拒绝,则会使用Handler方法进行处理。
Java中还提供了Executors工具类。
该工具类提供了几个用于创建线程池的静态方法,包括newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor等。
但是它的每个方法都会创建一个ThreadPoolExecutor对象。
不同的是每个对象的初始参数值不同。

什么是线程池,如何使用,为什么要用

什么是线程池:java.util.concurrent.Executors提供了java.util.concurrent.Executor接口的实现来创建线程池。
多线程技术主要解决处理器单元中多个线程的实现问题,它可以减少处理器单元的空闲时间,提高处理器单元的处理能力。

假设服务器完成任务所需的时间为:T1创建线程时间,T2在线程中执行任务,T3销毁线程时间。

如果:T1+T3比T2大很多,可以使用线程池来提高服务器性能。

线程池的作用:

线程池的作用是限制系统中执行线程的数量。

根据系统环境,可以自动或手动设置线程数,以达到最佳运行效果,少了会浪费系统资源,多了会造成系统拥塞、效率低下。
使用线程池来控制有多少线程和其他线程排队等待。
任务执行完毕后,队列前面的任务就会被取出并开始执行。
如果队列中没有进程等待,则该线程池资源处于等待状态。
当一个新任务需要运行时,如果线程池中有工作线程在等待,则它可以开始运行,否则进入等待队列。

为什么使用线程池:

1减少线程创建和销毁的次数,每个工作线程是可重用的,可以执行多个任务。

2.可以根据系统容量调整线程池中工作的线程数量,防止由于内存使用过多而导致服务器内存不足(每个线程需要1MB左右的内存,开的线程越多,内存就越多)它使用,最终崩溃)。

Java中线程池的顶层接口是Executor,但严格来说Executor并不是线程池,而只是执行线程的工具。
实际的线程池接口是ExecutorService。