线程池

概念

简介

线程池就是先创建一些线程,他们的集合称为线程池。

使用线程池,可以很好的提高性能,线程池再系统启动时即创建大量空闲的线程,程序奖一个任务传给线程池,线程池就会启动1条线程来执行此任务,执行结束后,线程不会死亡,而是再次返回线程池成为空闲状态,等待下一任务。

 

工作机制

1)在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后就在内部寻找空闲的线程,如果有就将任务交给空闲的线程。

2)一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。

 

使用线程池的原因

多线程运行时,系统不断的启动和关闭线程,成本非常高,会过度消耗系统资源,以及过度切换线程的危险,从而可能导致系统资源的崩溃。

 

常见线程池

SingleThreadExecutor

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

底层实现

 public static ExecutorService newSingleThreadExecutor() {
     return new FinalizableDelegatedExecutorService
         (new ThreadPoolExecutor(1, 1,
                                 0L, TimeUnit.MILLISECONDS,
                                 new LinkedBlockingQueue<Runnable>()));
 }

程序实验

 private static void SingleThreadExecutor() {
     // 一池 仅有 1个线程
     ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
     // 模拟10个用户请求线程
     try {
         for (int i = 1; i <= 10; i++) {
             singleThreadExecutor.execute(() -> {
                 System.out.println(Thread.currentThread().getName() + "	 处理请求");
             });
         }
     } catch (Exception e) {
         e.printStackTrace();
     } finally {
         singleThreadExecutor.shutdown();
     }
     // 程序运行结果
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
 }

线程池只有1个线程,所以仅有1个线程执行任务

 

CachedThreadPool

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

底层代码

 public static ExecutorService newCachedThreadPool() {
     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                   60L, TimeUnit.SECONDS,
                                   new SynchronousQueue<Runnable>());
 }

程序实验:

 private static void CachedThreadPool() {
     // 一池 n 个线程
     ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
     try {
         for (int i = 1; i <= 10; i++) {
             cachedThreadPool.execute(() -> {
                 System.out.println(Thread.currentThread().getName() + "	 处理请求");
             });
         }
     } catch (Exception e) {
         e.printStackTrace();
     } finally {
         cachedThreadPool.shutdown();
     }
     // 程序运行结果
     // pool-1-thread-1  处理请求
     // pool-1-thread-2  处理请求
     // pool-1-thread-3  处理请求
     // pool-1-thread-4  处理请求
     // pool-1-thread-5  处理请求
     // pool-1-thread-6  处理请求
     // pool-1-thread-7  处理请求
     // pool-1-thread-8  处理请求
     // pool-1-thread-10 处理请求
     // pool-1-thread-9  处理请求
 }

 

FixedThreadPool

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

底层代码

public static ExecutorService newFixedThreadPool(int nThreads) {
     return new ThreadPoolExecutor(nThreads, nThreads,
                                   0L, TimeUnit.MILLISECONDS,
                                   new LinkedBlockingQueue<Runnable>());
 }

程序实验:

 private static void FixedThreadPool() {
     // 一池5个线程
     ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
 ​
     // 模拟10个用户请求线程
     try {
         for (int i = 1; i <= 10; i++) {
             fixedThreadPool.execute(() -> {
                 System.out.println(Thread.currentThread().getName() + "	 处理请求");
             });
         }
     } catch (Exception e) {
         e.printStackTrace();
     } finally {
         fixedThreadPool.shutdown();
     }
     // 程序运行结果
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-2  处理请求
     // pool-1-thread-3  处理请求
     // pool-1-thread-4  处理请求
     // pool-1-thread-5  处理请求
 }

结果分析:可以一个线程处理多个任务,但是总线程数不会改变。

 

ScheduledThreadPool

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

底层代码

 public ScheduledThreadPoolExecutor(int corePoolSize) {
     super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
           new DelayedWorkQueue());
 }

程序实验:

 private static void ScheduledThreadPool() {
     ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
     try {
         for (int i = 1; i <= 10; i++) {
             scheduledThreadPool.execute(() -> {
                 System.out.println(Thread.currentThread().getName() + "	 处理请求");
             });
         }
     } catch (Exception e) {
         e.printStackTrace();
     } finally {
         scheduledThreadPool.shutdown();
     }
     // 程序运行结果
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
     // pool-1-thread-1  处理请求
 }

 

7大核心参数

简介

出自 ThreadPoolExecutor 的一个构造方法

 

 public ThreadPoolExecutor(int corePoolSize,
                           int maximumPoolSize,
                           long keepAliveTime,
                           TimeUnit unit,
                           BlockingQueue<Runnable> workQueue,
                           ThreadFactory threadFactory,
                           RejectedExecutionHandler handler) {
     
     if (corePoolSize < 0 ||
         maximumPoolSize <= 0 ||
         maximumPoolSize < corePoolSize ||
         keepAliveTime < 0)
         throw new IllegalArgumentException();
     if (workQueue == null || threadFactory == null || handler == null)
         throw new NullPointerException();
     this.acc = System.getSecurityManager() == null ?
             null :
             AccessController.getContext();
     this.corePoolSize = corePoolSize;
     this.maximumPoolSize = maximumPoolSize;
     this.workQueue = workQueue;
     this.keepAliveTime = unit.toNanos(keepAliveTime);
     this.threadFactory = threadFactory;
     this.handler = handler;
 }

corePoolSize

线程池中常驻核心线程数

maximumPoolSize

线程池可容纳同时执行的最大线程数,值必须 >= 1

keepAliveTime

多余的空闲线程存活时间。当前线程池数量超过corePoolSize时,当空闲时间到达keepAliveTime值时,多余空闲线程会被销毁直至只剩下corePoolSize为止

unit

keepAliveTime的时间单位

workQueue

任务队列,被提交但尚未执行的任务

threadFactory

表示生成线程池中的工作线程的线程工厂,用于创建线程,一般为默认的线程工厂即可

handler

拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝请求的Runable的策略

 

线程池工作原理

原理图

img

img

文字解释

当调用线程池的 execute() 方法时,线程池会做出以下判断:

1)如果 当前运行的线程数 小于 线程池的核心线程数,那么马上创建线程完成此任务

2)如果 运行的线程数 大于等于 线程池的核心线程数,那么将线程放进任务队列等待

3)如果 此时任务队列已满,且正在运行的线程数 小于 最大线程数,立即创建非核心线程执行这个任务

4)如果 此时任务队列已满,且正在运行的线程数 等于 最大线程数,啧线程池会启动饱和和 拒绝策略 来执行

 

4种拒绝策略

这4种拒绝策略都实现了 RejectedExecutionHandler

AbortPolicy(默认)

直接抛出RejectedExecutionException,异常阻止系统正常运行

CallerRunsPolicy

"调用者运行",一种调节机制,该策略既不会抛异常,又不会抛弃任务,而是将某些任务回退刀调用者,从而降低新任务的流量

DiscardOldestPolicy

抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

DiscardPolicy

直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案

 

阿里规范

1)

2)

 

 

原文地址:https://www.cnblogs.com/kzyuan/p/14470832.html