阿里大佬带你,深入理解线程池底层原理

  • 时间:
  • 浏览:5

为那此要使用应用程序池

在实际使用中,应用程序是很占用系统资源的,而是对应用程序管理不善很容易意味系统大问题。 而是,在大多数并发框架中而是使用应用程序池来管理应用程序,使用应用程序池管理应用程序主要有如下好处:

(1)降低资源消耗。通过复用已存在的应用程序和降低应用程序关闭的次数来尽而是降低系统性能损耗

(2)提升系统响应强度。通过复用应用程序,省去创建应用程序的过程,而是整体上提升了系统的响应强度

(3)提高应用程序的可管理性。 应用程序是稀缺资源 ,而是无限制的创建,不仅会消耗系统资源, 而是降低系统的稳定性,而是,都要使用应用程序池来管理应用程序。

应用程序池的工作原理

当原先并发任务提交给应用程序池,应用程序池分配应用程序去执行任务的过程如下:

应用程序池执行所提交的任务过程主要有原先十几个 阶段:

(1)先判断应用程序池中核心应用程序池所有的应用程序否有而是执行任务。 而是而是,则新创建原先应用程序执行刚提交的任务,而是,核心应用程序池中所有的应用程序而是执行任务,则进入(2)

(2)判断当前阻塞队列否有已满,而是未满, 则将提交的任务放置在阻塞队列中;而是,则进入(3)

(3)判断应用程序池中所有的应用程序否有而是执行任务, 而是那么 ,则创建原先新的应用程序来执行任务,而是,则交给 饱和策略 进行除理

应用程序池执行逻辑

通过ThreadPoolExecutor创建应用程序池后,提交任务后执行过程是咋样的,下面来通过源码来看一看。execute()法子 源码如下:

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
	//而是应用程序池的应用程序个数少于corePoolSize则创建新应用程序执行当前任务
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
	//而是应用程序个数大于corePoolSize而是创建应用程序失败,则将任务存中放去阻塞队列workQueue中
    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);
}

execute()执行过程:

execute法子 执行逻辑有原先几种情况汇报:

(1)而是当前运行的应用程序少于corePoolSize,则会创建新的应用程序来执行新的任务,即使应用程序池中的许多应用程序是空闲的;

(2)而是运行的应用程序个数等于而是大于corePoolSize且小于maximumPoolSize,则会将提交的任务存中放去阻塞队列workQueue中;

(3)而是当前workQueue队列已满句子,则会创建新的应用程序来执行任务;

(4)而是应用程序个数而是超过了maximumPoolSize,则会使用饱和策略RejectedExecutionHandler来进行除理增量的任务。

应用程序池的关闭

关闭应用程序池,而是 通过shutdown和shutdownNow这原先法子 。 它们的原理而是遍历应用程序池中所有的应用程序,而是依次中断应用程序。 shutdown和shutdownNow还是有不一样的地方:

  • shutdownNow首先将应用程序池的情况汇报设置为STOP,而是尝试停止所有的正在执行和未执行任务的应用程序,并返回等待英文执行任务的列表
  • shutdown而是将应用程序池的情况汇报设置为SHUTDOWN情况汇报,而是中断所有那么 正在执行任务的应用程序

而是 看出shutdown法子 会将正在执行的任务继续执行完,而shutdownNow会直接中断正在执行的任务。 调用了这原先法子 的任意原先,isShutdown法子 而是返回true, 当所有的应用程序都关闭成功,才表示应用程序池成功关闭,这时调用isTerminated法子 才会返回true。

咋样合理配置应用程序池参数

要想合理的配置应用程序池,就都要首先分析任务形态学 ,而是 从以下十几个 层厚来进行分析:

  • 任务的性质:CPU密集型任务,IO密集型任务和混合型任务。
  • 任务的优先级:高,中和低。
  • 任务的执行时间:长,中和短。
  • 任务的依赖性:否有依赖许多系统资源,如数据库连接。
  1. CPU密集型任务配置尽而是少的应用程序数量,如配置(N cpu)+原先应用程序的应用程序池。
  2. IO密集型任务则而是都要等待英文IO操作,应用程序并而是老是 在执行任务,则配置尽而是多的应用程序,如2 * (N cpu)。
  3. 混合型的任务,而是而是 拆分,则将其拆分成原先CPU密集型任务和原先IO密集型任务,倘若这原先任务执行的时间相差而是越多,那么 分解后执行的吞吐率要高于串行执行的吞吐率,而是这原先任务执行时间相差越多,则没必要进行分解。
  4. 当他们 而是 通过Runtime.getRuntime().availableProcessors()法子 获得当前设备的CPU个数。

优先级不同的任务而是 使用优先级队列PriorityBlockingQueue来除理。它而是 让优先级高的任务先得到执行,都要注意的否有则老是 有优先级高的任务提交到队列里,那么 优先级低的任务而是永远而是 了执行。

执行时间不同的任务而是 交给不同规模的应用程序池来除理,而是也而是 使用优先级队列,让执行时间短的任务先执行。

依赖数据库连接池的任务,而是应用程序提交SQL后都要等待英文数据库返回结果,而是 等待英文的时间越长CPU空闲时间就越长 ,那么 应用程序数应该设置越大,原先要能更好的利用CPU。

阻塞队列最好是使用 有界队列 ,而是采用无界队列句子,一旦任务积压在阻塞队列中句子就会占用越多的内存资源,甚至会使得系统崩溃。

ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor继承了ThreadPoolExecutor类, 而是,整体上功能一致,应用程序池主要负责创建应用程序(Worker类), 应用程序从阻塞队列中不断获取新的异步任务,直到阻塞队列中而是那么 了异步任务为止。 而是相较于ThreadPoolExecutor来说,ScheduledThreadPoolExecutor 具有 延时执行任务 和 周期性执行任务 的形态学 , ScheduledThreadPoolExecutor重新设计了任务类ScheduleFutureTask,  ScheduleFutureTask重写了run法子  使其具有可延时执行和可周期性执行任务的形态学 。 另外,阻塞队列DelayedWorkQueue是可根据优先级排序的队列,采用了堆的底层数据形态学 , 使得与当前时间相比,将待执行时间越靠近的任务放置到队头,以便应用程序要能获取到任务进行执行

应用程序池无论是ThreadPoolExecutor还是ScheduledThreadPoolExecutor, 在设计时的原先关键主次是: 任务 、 执行者 以及 任务结果 。 它们的设计思想也是完整版将这原先关键主次进行了解耦。

执行者

任务的执行机制,完整版交由Worker类,也而是进一步了封装了Thread。 向应用程序池提交任务,无论为ThreadPoolExecutor的execute法子 和submit法子 , 还是ScheduledThreadPoolExecutor的schedule法子 ,而是先将任务移入到阻塞队列中, 而是通过addWork法子 新建了Work类,并通过runWorker法子 启动应用程序,并 不断的从阻塞对列中获取异步任务执行交给Worker执行,直至阻塞队列中无法取到任务为止。

任务

在ThreadPoolExecutor和ScheduledThreadPoolExecutor中任务是指实现了Runnable接口和Callable接口的实现类。 ThreadPoolExecutor中会将任务转再加FutureTask类, 而在ScheduledThreadPoolExecutor中为了实现可延时执行任务和周期性执行任务的形态学 , 任务会被转再加ScheduledFutureTask类,该类继承了FutureTask,并重写了run法子 。

任务结果

在ThreadPoolExecutor中提交任务后,获取任务结果而是 通过Future接口的类, 在ThreadPoolExecutor中实际上为FutureTask类, 而在ScheduledThreadPoolExecutor中则是ScheduledFutureTask类

应用程序池的情况汇报

应用程序池的情况汇报有:

  • RUNNING:能接受新提交的任务,而是也要能除理阻塞队列中的任务;
  • SHUTDOWN:不再接受新提交的任务,而是而是 除理存量任务(即阻塞队列中的任务);
  • STOP:不再接受新提交的任务,而是除理存量任务;
  • TIDYING:所有任务都已终止;
  • TERMINATED:默认是那此而是做的,而是作为原先标识。

情况汇报转移如下图所示:

工作应用程序的生命周期:

原文链接

原文:http://blog.itpub.net/69917506/viewspace-2645729/h

专家姓名:李红

本文由

lihong

发布在

ITPUB

,转载此文请保持文章完整版性,并请附上文章来源(ITPUB)及本页链接。

原文链接:http://www.itpub.net/2019/05/28/1950/