简介

本文介绍Java线程池的原理,包括:线程池的流程、线程池的结构、线程池的任务状态。

执行流程

流程图


java oncurrent 线程池执行 java线程池执行流程_工作队列


  1. 提交任务
  2. 线程池判断核心线程池(核心线程数)里的线程是否已经满了(全都在执行任务)。
  1. 如果不是:看线程数是否到达指定的核心线程池的大小
  1. 如果不是:则创建一个新的线程来执行任务。
  2. 如果是:使用空闲的线程来执行任务
  1. 如果是,则进入下个流程。
  1. 线程池判断工作队列是否已满。
  1. 如果没有满,则将新提交的任务存储在这工作队列里。
  2. 如果工作队列满了,则进入下一个流程。
  1. 队列见:Java多线程--队列(Queue)--使用/教程/实例_IT利刃出鞘的博客
  1. 线程池判断线程池的所有线程(最大线程数)是否已经满了(全都在执行任务)。
  1. 如果不是:看线程数是否到达指定的最大线程池的大小
  1. 如果不是:则创建一个新的线程来执行任务。
  2. 如果是:使用空闲的线程来执行任务
  1. 如果是:则交给饱和策略来处理这个任务。

线程池结构

组成部分

一个线程池包括四个基本部分

  1. 线程管理池(ThreadPool)
  1. 用于创建并管理线程池,有创建,销毁,添加新任务;
  1. 工作线程(PoolWorker)
  1. 线程池中的线程在没有任务的时候处于等待状态,可以循环的执行任务;
  1. 任务接口(Task)
  1. 每个任务必须实现接口,用来提供工作线程调度任务的执行,规定了任务的入口以及执行结束的收尾工作和任务的执行状态等;
  1. 任务队列
  1. 用于存放没有处理的任务,提供一种缓存机制。

类的关系

java oncurrent 线程池执行 java线程池执行流程_线程池_02

 

  • Executor是一个顶层接口
  • 只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型
  • 从字面意思可以理解,就是用来执行传进去的任务的。
  • ExecutorService接口继承了Executor接口
  • 声明了一些方法:submit、invokeAll、invokeAny以及shutDown等
  • 抽象类AbstractExecutorService实现了ExecutorService接口
  • 实现了ExecutorService中声明的所有方法
  • ThreadPoolExecutor继承了类AbstractExecutorService

比较重要的类:

描述

ExecutorService

真正的线程池接口。

ScheduledExecutorService

能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。

ThreadPoolExecutor

ExecutorService的默认实现。

ScheduledThreadPoolExecutor

继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

线程池状态

状态图

java oncurrent 线程池执行 java线程池执行流程_Java_03

线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated。

状态

说明

状态切换

RUNNING

线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。创建时会调用此语句:

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!

SHUTDOWN

线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。

调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。

STOP

线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。

TIDYING

当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。

当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

TERMINATED

线程池彻底终止,就变成TERMINATED状态。

线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。