深入浅出Java多线程(十二)之ThreadPool(上)

293 阅读3分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

前言

线程,程序执行流的最小执行单位,是行程中的实际运作单位,经常容易和进程这个概念混淆。那么,线程和进程究竟有什么区别呢?首先,进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程,而线程,是运行中的实际的任务执行者。可以说,进程中包含了多个可以同时运行的线程。

ThreadPool

线程池原理

​ 所谓线程池,通俗的理解就是有一个池子,里面存放着已经创建好的线程,当有任务提交给线程池执行时,池子中的某个线程会主动执行任务。如果池子中的线程数量不够应付数量众多的任务时,则需要自动扩充新的线程到池子中,但是该数量是有限的的,就好比池塘的水界线一样。当任务比较少的时候,池子中的线程能够自动回收,释放资源。为了能够异步地提交任务和缓存未被处理的任务,需要有一个任务队列。

  • 任务队列:用于缓存提交的任务
  • 线程数量管理功能:一个线程池必须能够很好地管理和控制线程数量
    • init:创建线程池时初始的线程数量 init;
    • max:线程池自动扩充时最大线程数量
    • core:在线程池空闲时需要释放线程但是也要维护一定数量的活跃数量或者核心数量
    • 三者关系:init <= core <= max
  • 任务拒绝策略:如果线程数量已达到上限且任务队列已满,则需要有相应的拒绝策略来通知任务提交者
  • 线程工厂:主要用于个性化定制线程,比如将线程设置为守护线程以及设置线程名称等。
  • QueueSize:任务队列主要存放提交的Runnable,但是为了防止内存溢出,需要有limit数量对其进行控制
  • Keepedalive:时间,该时间主要决定线程各个重要参数自动维护的时间间隔。

ThreadPool

  • execute (Runnable runnable):该方法接受提交Runnable 任务
  • shutdown():关闭并且销毁线程池
  • getInittSize():返回线程池的初始线程数量
  • getMaxSize():返回线程池最大的线程数量
  • getCoreSize():返回核心线程数量
  • getQueueSize():返回当前线程池任务数量
  • getActiveCount():返回线程池中活跃的线程数量
  • isShutDown():判断线程池是否已被销毁

RunnableQueue

runnableQueue主要用于存放提交的Runnable,该Runnable是一个BlockedQueue,并且有limit的限制

  • offer(Runnable runnable):方法主要用于将任务提交到队列中
  • Runnable take():方法主要从队列中获取相应的任务
  • int size():方法主要用于获取当前队列的Runnable数量

ThreadFactory

ThreadFactory提供了创建线程的接口,以便于个性化地定制Thread,比如Thread应该被放到哪个Group中,优先级、线程级、线程名字以及是否为守护线程等

@FunctionalInterface
public interface ThreadFactory{
    Thread createThread(Runnable runnable);
}

其中,createThread(Runnable runnable) 用于创建线程

四种常见的线程池:

  • CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。

  • SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。

  • SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。

  • FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程