1.线程池原理

假设初始化一个线程池,核心线程池数(corePoolSize)是5,最大线程数(maxPoolSize)是10;初始化的时候线程池里是空的。阻塞队列里面也没有任务;当来了一个任务时,线程池中初始化一个线程,再来一个任务就在初始化一个,当线程数量达到5个时,第6个任务就会放到阻塞队列中,如果其中一个线程空闲了,就会从队列中获取第6个任务继续执行;当任务产生的速度比消费的的速度快,阻塞队列又满了的时候,就会根据最大线程数去新建线程处理阻塞队列里的任务;当线程池中的线程达到最大线程数,阻塞队列也满了,需要通过自定义reject函数处理任务(RejectedExecutionHandler----拒绝策略);

2.关键参数

corePoolSize

线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。

maximumPoolSize

线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize;

keepAliveTime

线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间;默认情况下,该参数只在线程数大于corePoolSize时才有用;



3.概念

  1. Worker和Task的区别,Worker是当前线程池中的线程,而task虽然是runnable,但是并没有真正执行,只是被Worker调用了run方法,后面会看到这部分的实现。
  2. maximumPoolSize和corePoolSize的区别:这个概念很重要,maximumPoolSize为线程池最大容量,也就是说线程池最多能起多少Worker。corePoolSize是核心线程池的大小,当corePoolSize满了时,同时workQueue full(ArrayBolckQueue是可能满的) 那么此时允许新建Worker去处理workQueue中的Task,但是不能超过maximumPoolSize。超过corePoolSize之外的线程会在空闲超时后终止。


4.使用例子

public class ThreadPoolTest {
     private static Executor ex=Executors.newFixedThreadPool(10);
     public static void main(String[] args) {
         for (int i = 0; i < 20; i++) {
             ex.execute(new Task());
         }
     }
     
     static class Task implements Runnable{
         @Override
         public void run() {
             System.out.println("当前线程名字"+Thread.currentThread().getName());
         }
         
     }
 }



这里:通过Executor.execute()方法提交的任务,必须实现Runnable接口,该方式提交的任务不能获取返回值,因此无法判断任务是否执行成功;通过ExecutorService.submit()方法提交的任务,可以获取任务执行完的返回值。