Executors 提供了五种常用的线程池

 

Executors的其中四种线程池其实都是调用ThreadPoolExecutor实现的:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue

 

ThreadPoolExecutor核心参数介绍:

corePoolSize:核心线程数

1.核心线程会一直存活,及时没有任务需要执行
2.当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理

maximumPoolSize:最大线程数

1.当线程数 >= corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务
2.当线程数 = maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常

keepAliveTime:线程空闲时间

1.超过corePoolSize后新创建的线程会根据keepAliveTime来控制该线程的空闲存活时间

2.如果调用了ThreadPoolExecutor.allowCoreThreadTimeOut(boolean)的方法,将allowCoreThreadTimeOut(允许核心线程超时)修改为true,则线程池中所有线程都会根据keepAliveTime来控制该线程的空闲存活时间(包括核心线程)

unit:keepAliveTime的时间单位

workQueue:阻塞队列

1.当前线程池中的线程数目 >= corePoolSize,则每来一个任务,会尝试将其添加到该队列当中

 

注:在demo中主线程一定要写延迟,否则当主方法结束时,线程池会自动被回收,所有的子线程都会结束。下一章会介绍在springboot中配置线程池。

 

1)newCachedThreadPool

可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。该线程池最大程度保证每一个请求都能立即被处理。

源码:

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

缺点:因为其最大允许线程数为 Integer.MAX_VALUE ,所以当同时创建的线程数过多时,会造成OOM(内存溢出错误)

示例代码:

@Testpublic void testCachedThreadPool() {
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
  // 子线程1
    cachedThreadPool.execute(() -> {        for (int i = 0; i < 10; i++) {            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("a" + i);
        }
    });
  // 子线程2
    cachedThreadPool.execute(() -> {        for (int i = 0; i < 10; i++) {            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("b" + i);
        }
    });
  // 主线程延时
    try {
        Thread.sleep(25000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

 

2)newFixedThreadPool

定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

源码:

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

缺点:因为LinkedBlockingQueue队列是无参构造,默认最大可存放请求数为 Integer.MAX_VALUE ,所以当队列中存放请求数过多时,会造成OOM(内存溢出错误)

示例代码:

@Test    public void testFixedThreadPool() {
     // 控制最大并发数为2
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
     // 子线程1
        fixedThreadPool.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.err.println("a" + i);
            }
        });
     // 子线程2
        fixedThreadPool.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.err.println("b" + i);
            }
        });
     // 子线程3
        fixedThreadPool.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.err.println("c" + i);
            }
        });
     // 主线程延时        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

 

3)newScheduledThreadPool

周期性线程池,支持任务定时及周期性的执行。

源码:

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

缺点:同newCachedThreadPool

示例代码:

@Test    public void testScheduledThreadPool(){
     // 创建一个最大并发数为5的周期性线程池
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);        // 子线程1 延迟三秒后执行一次任务
        scheduledThreadPool.schedule(() -> {
            System.out.println("a 当前时间:" + new Date());
        }, 3, TimeUnit.SECONDS);        // 子线程2 延迟一秒后开始执行任务,之后每隔三秒执行一次任务
        scheduledThreadPool.scheduleAtFixedRate(() -> {            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("b 当前时间:" + new Date());
        }, 1,3, TimeUnit.SECONDS);        // 子线程3 延迟一秒后开始执行任务,等上一个任务完成之后再间隔三秒执行下一次任务
        scheduledThreadPool.scheduleWithFixedDelay(() -> {            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("c 当前时间:" + new Date());
        }, 1,3, TimeUnit.SECONDS);        // 主线程延时
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

 

4)newSingleThreadExecutor

单线程化线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

源码:

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

缺点:同newFixedThreadPool

示例代码:

@Test    public void testSingleThreadExecutor(){
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();        // 子线程1
        singleThreadExecutor.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("a" + i);
            }
        });        // 子线程2
        singleThreadExecutor.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("b" + i);
            }
        });        // 主线程延时
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

以上四种都是ThreadPoolExecutor的扩展,下面介绍第五种线程池newWorkStealingPool。

 

5)newWorkStealingPool

抢占式操作线程池,JDK1.8 版本加入的一种线程池,是新的线程池类ForkJoinPool的扩展,能够合理的使用CPU进行对任务的并行操作。

ForkJoinPool构造函数:

private ForkJoinPool(int parallelism,
                         ForkJoinWorkerThreadFactory factory,
                         UncaughtExceptionHandler handler,                         int mode,
                         String workerNamePrefix) {        this.workerNamePrefix = workerNamePrefix;        this.factory = factory;        this.ueh = handler;        this.config = (parallelism & SMASK) | mode;        long np = (long)(-parallelism); // offset ctl counts
        this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
    }

由于目前我还不是很了解newWorkStealingPool、ForkJoinPool,就先提一下,顺便挖个坑,等后期了解过了,会另开一章进行补充和探讨。

 

newWorkStealingPool源码:

public static ExecutorService newWorkStealingPool() {        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,             null, true);
    }

 

示例代码:

@Test    public void testWorkStealingPool(){
        ExecutorService workStealingPool = Executors.newWorkStealingPool();        // 子线程1
        workStealingPool.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("a" + i);
            }
        });        // 子线程2
        workStealingPool.execute(() -> {            for (int i = 0; i < 10; i++) {                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("b" + i);
            }
        });        // 主线程延时
        try {
            Thread.sleep(25000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }