面试题:你分析过线程池源码吗?

1.为什么要用线程池?

降低系统资源消耗

提高线程可控性

2.如何创建线程池?

JDK8中提供了5种创建线程池的方法

(1). newFixThreadPool

创建固定大小的线程池,可控制线程最大并发数,超过的线程会在队列中等待

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

(2).(JDK8新增)   newWorkStealingPool

会根据所需的并发数来动态创建和关闭线程,能够合理的使用CPU进行对任务进行并发操作,所以很适合使用在很耗时的任务上

public static ExecutorService newWorkStealingPool(int parallelism) {
    return new ForkJoinPool
        (parallelism,
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}

这里返回的是一个ForkJoinPool对象

public ForkJoinPool(int parallelism,
                        ForkJoinWorkerThreadFactory factory,
                        UncaughtExceptionHandler handler,
                        boolean asyncMode) {
        this(checkParallelism(parallelism),
             checkFactory(factory),
             handler,
             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
             "ForkJoinPool-" + nextPoolId() + "-worker-");
        checkPermission();
    }

使用一个无限队列来保存需要执行的任务,可以传入线程的数量,不传入的话,默认使用当前计算机中可以使用的CPU数量,使用分治法来解决问题,使用fork()和join()来进行调用

(3).newCashedThreadPool

创建一个可缓存的线程池,可以灵活回收空闲线程,如果无法回收,则新建线程

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

(4).newSingleThreadPoolExecutor

创建一个单线程的线程池

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

(5).newScheduledThreadPool

创建一个定长线程池,支持定时以及周期性任务执行

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

3.源码结构(Executor框架结构)

从上往下依次是:

Executor

一个运行新任务的简单接口

ExecutorService

扩展了Executor接口,添加了一些用来管理执行器生命周期和任务生命周期的方法

AbstractExecutorService

对ExecutorService接口的抽象类实现

ThreadPoolExecutor

Java线程池的核心实现

4.线程池状态的转换模型

running:

线程池一旦被创建,就处于running状态,能够接收新任务,以及对已添加的任务进行处理

shutdown:

不能接收新任务,但能够处理已添加的任务

stop:

不接受新任务,不处理已添加的任务,并且会中断正在处理的任务

tidying:

当所有的任务已经终止,线程池就会变成tidying状态

terminated:

线程池彻底终止,就会变成terminated状态

 

 

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值