Java线程池详解(二)

1、背景

前一篇文章对ThreadPoolExecutor的配置进行了详细的阐述Java线程池详解(一),本节我们将分析Java中最常见的四类具有不同功能的线程池,它们都是通过直接或间接配置ThreadPoolExecutor来实现自己的特性,这四类线程池分别是(通过Executors工具类来创建):

(1)newCachedThreadPool:线程数量不定的线程池,只有非核心线程,并且其最大线程数为Integer.MAX_VALUE,当线程池中的线程都处于活动状态时,线程池将创建新线程来执行任务,否则将利用空闲线程执行任务。其线程池具有超时策略,超过60s的闲置线程将被回收,适合执行大量的耗时较少的任务。

(2)newFixedThreadPool:线程数固定的线程池,其只有核心线程并且不会被回收,所以当所有线程都处于活动状态时,新任务都将处于等待状态,直到有线程空闲下来。

(3)newScheduledThreadPool 创建核心线程数固定,非核心线程数为Integer.MAX_VALUE的线程池,当非核心线程闲置时会被立即回收,主要用于执行定时任务和固定周期的重复任务。

(4)newSingleThreadExecutor 创建只有一个核心线程的线程池,它只会用唯一的工作线程来执行任务,以确保所有的任务都在同一线程中按顺序执行,无需处理线程同步问题。

2、四类线程详解

以上只是对四类线程池总的概述,接下来我们将单独详细分析,每种线程池我们都给出其创建源码和示例。

1、CachedThreadPool

//创建线程池
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        //创建ThreadPoolExecutor对象,核心线程数0,线程最大数Integer.MAX_VALUE,超时时长60s
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue(),
                                      threadFactory);
    }
//测试代码
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 20; i++) {
            final int index = i;
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

20个数会在一瞬间全部打印出来。

2、FixedThreadPool

//创建线程池
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        //创建ThreadPoolExecutor对象,此时只有核心线程,并且没有闲置超时策略
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue(),
                                      threadFactory);
    }
//测试代码
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 20; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

此时核心线程只有4个,每次只能输出4个数,然后等待3秒后将输出下一波四个数。

3、ScheduledThreadPool

//创建线程池
public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        //创建ScheduledThreadPoolExecutor对象
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }

public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        //调用父类的构造器,核心线程数固定,非核心线程数Integer.MAX_VALUE,非核心线程闲置会立即回收
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }

由代码看见,其最终还是通过创建ThreadPoolExecutor对象来创建线程池。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.schedule(new Runnable() {
            public void run() {
                System.out.println("delay 3 seconds");
            }
        }, 3, TimeUnit.SECONDS);

表示延迟3秒后执行一次;

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println("delay 1 seconds, and excute every 3 seconds");
            }
        }, 1, 3, TimeUnit.SECONDS);

表示延迟1秒后每3秒执行一次;

4、SingleThreadExecutor

//创建线程池
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            //创建只有一个核心线程,没有非核心线程的线程池,所有任务按序执行
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue(),
                                    threadFactory));
    }
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 20; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

此时核心线程数只有一个,没有非核心线程数,所有任务按序执行,每隔3s打印一次数据。

好啦,四种常用线程池我们就分析到这里啦。

你可能感兴趣的:(Java)