面试系列 - java线程池

面试系列 - java线程池

线程池在日常开发中还是很常见的。比如要刷数据或者日常开发中有大量数据要处理的时候,为了提高响应时间就需要开多线程来实现。

Executors 快速创建线程池

java中可以通过 Executors快速创建线程池,具体的用法有三种(Executors.newXXX):

方法 特点
newFixedThreadPool(int nThreads) 指定线程数的线程池
newSingleThreadExecutor() 单个线程的线程池
newCachedThreadPool() 不限线程数的线程池

具体的源码如下:

/*指定线程数的线程池*/
public static ExecutorService newFixedThreadPool(int nThreads) {
    
    
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
       
/*单个线程的线程池*/
public static ExecutorService newSingleThreadExecutor() {
    
    
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

/*不限线程数的线程池*/
public static ExecutorService newCachedThreadPool() {
    
    
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

我们可以看到快速创建线程池的底层还是使用的ThreadPoolExecutor这个方法。只是针对不同的方法做了不同的参数设置,如果在不关心其他参数(超时时间、等待队列、拒绝策略)设置的情况下,可以使用快速方法创建线程池。

ThreadPoolExecutor 构造器

参数介绍

public ThreadPoolExecutor(int corePoolSize, //核心线程数量 默认即使处于空闲状态(不会回收 可以通过参数设置allowCoreThreadTimeOut)
                          int maximumPoolSize, //最大线程数
                          long keepAliveTime, //超过corePoolSize 线程的存活时间
                          TimeUnit unit,//keepAliveTime的单位
                          BlockingQueue<Runnable> workQueue, //任务队列(保存已经提交但是还没有执行完毕的线程),当核心线程不空闲时,任务将会被添加到任务队列(execute之后没有线程执行)
                          ThreadFactory threadFactory,//创建线程的工厂
                          RejectedExecutionHandler handler) //线程数量 = maximumPoolSize & workQueue 满了 新的线程请求拒绝策略
/*
 * 新线程请求到来时 corePoolSize > workQueue > maximumPoolSize
 * 当corePoolSize 不满时就创建新的线程(核心)
 * 当corePoolSize满时 & 队列未满 创建新的线程 往队列里添加
 * 当corePoolSize满时 & 队列满 & 总线程数 < maximumPoolSize 创建新线程(普通线程,超时会被回收)
 * 当corePoolSize满时 & 队列满 & 总线程数 = maximumPoolSize handler处理(拒绝策略)
 */

拒绝策略

拒绝策略 拒绝方法
AbortPolicy 抛出异常 RejectedExecutionException
DiscardPolicy 什么也不做,直接忽略
DiscardOldestPolicy 丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置
CallerRunsPolicy 直接由提交任务者执行这个任务

Runnable & Callable

区别:Callable是jdk1.5对Runnable的一种补充,可以返回线程的执行结果可以抛异常

1、方法签名不同
void Runnable.run(),
V Callable.call() throws Exception
2、Callable允许有返回值
3、Callable允许抛出异常

//不返回结果
void execute(Runnable command);
//future.get()可以获取执行结果
<T> Future<T> submit(Callable<T> task);
//future.get()返回入参result
<T> Future<T> submit(Runnable task, T result);
//future.get()返回null
Future<?> submit(Runnable task);
//forEach(List<Future<T>>) {future.get()}可以获取执行结果 0<i<thirdSize是线程的index
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

关闭线程池

/*正在执行的线程、已在等待队列里的任务会继续执行下去,不再接受新任务 ,异步中断闲置的的线程*/
void shutdown();

/*尝试停止所有正在执行的任务,停止处理等待的任务,并返回等待执行的任务列表*/
List<Runnable> shutdownNow();

/* 返回是否已经关闭 */
boolean isShutdown();

/*所有的线程是否都已经执行完毕等待关闭*/
boolean isTerminated();

/*阻塞,直到所有任务在关闭请求后完成执行(发生超时/当前线程中断)*/
boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

猜你喜欢

转载自blog.csdn.net/automal/article/details/107960198