大厂面试必会线程池ThreadPoolExecutor

2019-08-28 15:27:49 浏览数 (1)

线程池呀

线程池及其各参数

我们是谁?

程序员!

我们要什么?

不知道!

什么时候要?

现在要!

ThreadPoolExecutor是用来处理异步任务的接口,可以将其理解为一个线程池和一个任务队列。 下面给出其构造方法。当大小达到coreSize后任务会被放入队列,队列满之后就会创建新的线程,直到达到maximumPoolSize。

代码语言:javascript复制
    public ThreadPoolExecutor(int corePoolSize, // 核心线程数
                              int maximumPoolSize, // 池内最大线程数
                              long keepAliveTime, // 超过核心线程数的线程会被终止的等待时间
                              TimeUnit unit, // keepAliveTime 的时间单位
                              BlockingQueue<Runnable> workQueue, // 任务队列
                              ThreadFactory threadFactory) { // 创建线程的工厂对象
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

通过改变ThreadPoolExecutor的构造方法的参数,这样我们就可以构造各种我么你想要的线程池,常见的有以下三种。

1.FixedThreadPool-线程池大小固定 队列无界以下代码核心线程数和最大线程数是设置成相同数值,任务队列是没有限制大小的。当现场数达到nThreads时,新的任务会被加入到队列中。缺点:队列数量没有限制,容易造成内存问题。

代码语言:javascript复制
 public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                 0L, TimeUnit.MILLISECONDS,
                                 new LinkedBlockingQueue<Runnable>());
}

2.SingleThreadExecutor-线程池大小为1 任务队列无界 线程数和核心线程数都是1,外部使用FinalizableDelegated ExecutorService类进行了包装,主要是防止动态修改线程数量功能。由于是单线程,一旦有异常,将重新开启一个线程进行工作。缺点:任务队列无界,容易造成内存问题。

代码语言:javascript复制
public static ExecutorService newSingleThreadExecutor() {
       return new FinalizableDelegatedExecutorService
           (new ThreadPoolExecutor(1, 1,
                                   0L, TimeUnit.MILLISECONDS,
                                   new LinkedBlockingQueue<Runnable>()));
}

3.CachedThreadPool - 线程池无限大,等待队列为1

SynchronousQueue是一个只有1个元素的队列,当有多个任务来时就开始创建线程,且60秒没接到任务的线程就会终止。

代码语言:javascript复制
public static ExecutorService newCachedThreadPool() {
       return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                     60L, TimeUnit.SECONDS,
                                     new SynchronousQueue<Runnable>());
 }

4.自定义队列大小及拒接策略,在传入队列参数的时候可以指定队列大小,以及再传入拒接策。RejectedExecutionHandler 就是拒绝策略,我们可以写一个它的实现然后传入,这样就可以实现自己的拒绝策略啦。

代码语言:javascript复制
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                    BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
代码语言:javascript复制
// RejectedExecutionHandler 默认实现
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
         throw new RejectedExecutionException("Task "   r.toString()  
                                               " rejected from "  
                                               e.toString());
        }

0 人点赞