美团面试官问Java线程池,这样的回答让他竖起了大拇指!

这周我投递出了简历,岗位是java后端开发工程师。这周美团面试官给我进行了面试。面试过程中他问了线程池,今天详细讲一讲Java线程池。

线程池

线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。

start();//创建一定数量的线程池,进行线程循环
stop();//停止所有线程循环,回收所有资源
addTask();//添加任务

Excutors创建线程池便捷方法如下:

Executors.newFixedThreadPool(100);//创建固定大小的线程池
Executors.newSingleThreadExecutor();//创建只有一个线程的线程池
Executors.newCachedThreadPool();//创建一个不限线程数上限的线程池,任何提交的任务都将立即执行

对于服务端需要长期运行的程序,创建线程池应该使用ThreadPoolExecutor的构造方法

public ThreadPoolExecutor(
      int corePoolPoolSize,//线程池长期维持的线程数
      int maximumPoolSize, //线程数的上限
      long keepAliveTime,//空闲线程存活时间
      TimeUnit unit,//时间单位
      BlockingQueue<Runnable> workQueue,//任务的排队队列
      ThreadFactory threadFactory,//新线程的产生方式
      RejectedExecutionHandler handler//拒绝策略
  )

java线程池有7大参数,4大特性。

特性一:当池中正在运行的线程数(包括空闲线程)小于corePoolSize时,新建线程执行任务。

特性二:当池中正在运行的线程数大于等于corePoolSize时,新插入的任务进入workQueue排队(如果workQueue长度允许),等待空闲线程来执行。

特性三:当队列里的任务数达到上限,并且池中正在运行的线程数小于maximumPoolSize,对于新加入的任务,新建线程。

特性四:当队列里的任务数达到上限,并且池中正在运行的线程数等于maximumPoolSize,对于新加入的任务,执行拒绝策略(线程池默认的拒绝策略是抛异常)。

种类

一、newCachedThreadPool

核心线程数为0,最大线程数为Interger. MAX_VALUE

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

1、作用

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们,并在需要时使用提供的ThreadFactory创建新线程。Java进阶路线:https://www.yoodb.com/

2、特征

1)线程池中数量没有固定,可达到最大值(Interger. MAX_VALUE

2)线程池中的线程可进行缓存重复利用和回收(回收默认时间为1分钟)

3)当线程池中,没有可用线程,会重新创建一个线程

3、创建方式

Executors.newCachedThreadPool();

二、newFixedThreadPool

核心线程数与最大线程数均为指定的nThreads

空闲线程的存活时间是0

工作队列是无界队列

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

1、作用

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。

2、特征

1)线程池中的线程处于一定的量,可以很好的控制线程的并发量;

2)线程可以重复被使用,在显示关闭之前,都将一直存在;

3)超出一定量的线程被提交时候需在队列中等待。

3、创建方式

Executors.newFixedThreadPool(int nThreads);//nThreads为线程的数量
Executors.newFixedThreadPool(int nThreads,ThreadFactory threadFactory);//nThreads为线程的数量,threadFactory创建线程的工厂方式

三、newSingleThreadExecutor

核心线程数与最大线程数均为1

工作队列是无界队列

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

1、作用

创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。

可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

与其他等效的 newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。

2、特征

线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行。

3、创建方式

Executors.newSingleThreadExecutor();
Executors.newSingleThreadExecutor(ThreadFactory threadFactory);// threadFactory创建线程的工厂方式

四、newScheduledThreadPool

指定核心线程数corePoolSize

最大线程数是Integer.MAX_VALUE

DelayedWorkQueue:任务队列会根据任务延时时间的优先级进行执行

public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {
        ....................
	/**
     * Creates a new {@code ScheduledThreadPoolExecutor} with the
     * given core pool size.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
    .......................
}

1、作用

创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。另外,公众号Java精选,回复java面试,获取面试资料。

2、特征

1)线程池中具有指定数量的线程,即便是空线程也将保留;

2)可定时或者延迟执行线程活动。

3、创建方式

Executors.newScheduledThreadPool(int corePoolSize);// corePoolSize线程的个数
newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);// corePoolSize线程的个数,threadFactory创建线程的工厂

五、newSingleThreadScheduledExecutor

1、作用

创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。

2、特征

1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行;

2)可定时或者延迟执行线程活动。

3、创建方式

Executors.newSingleThreadScheduledExecutor();
Executors.newSingleThreadScheduledExecutor(ThreadFactory threadFactory);//threadFactory创建线程的工厂

工作队列

一、SynchronousQueue:直接提交

是工作队列的默认选项,将任务直接提交给线程而不保持。

如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。

优缺点

优点:可以避免在处理可能具有内部依赖性的请求集时出现锁。

直接提交通常要求无界maximumPoolSizes以避免拒绝新提交的任务。

当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。

二、ArrayBlockingQueue:无界队列

在所有核心线程都忙时,新任务在队列中等待。

因此,仅创建corePoolSize线程即可。(maximumPoolSize的值没有任何作用。)

当每个任务完全独立于其他任务时,因此任务不会影响彼此的执行。

优缺点

优点:例如,在网页服务器中,尽管这种排队方式对于消除短暂的突发请求很有用。

缺点:当命令请求到达速度比其处理速度更快时,工作队列无限制增长。

三、LinkedBlockingQueue:有界队列

当与有限的maximumPoolSizes一起使用时,有界队列有助于防止资源耗尽,但是调整和控制起来会更加困难。

队列大小和最大池大小可以相互权衡:

1)使用大队列和小池可以最大程度地减少CPU使用率,操作系统资源和上下文切换开销,但可能导致人为地降低吞吐量。

2)如果任务频繁阻塞(例如如果它们是受I/O约束的),则系统可能可以为非预定的更多线程安排时间。

3)使用小队列通常需要更大的池大小,这会使CPU繁忙,但可能会遇到不可接受的调度开销,这也会降低吞吐量。

拒绝策略

AbortPolicy:处理程序遭到拒绝将抛出运行时RejectedExecutionException

DiscardPolicy:不能执行的任务将被删除;

DiscardOldestPolicy:如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程);

CallerRunsPolicy:线程调用运行该任务的execute本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。

RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务

参考链接:

https://www.cnblogs.com/cdf-opensource-007/p/8769777.html
https://www.cnblogs.com/vince66/p/9325638.html
http://www.mamicode.com/info-detail-2740441.html

总结

咱们玩归玩,闹归闹,别拿面试开玩笑。

线程池记忆口诀:七个参数,四大特性,五个种类、三大工作队列、四大拒绝策略;

线程池,在面试中出现的次数非常多,大家面试前要把知识点记牢。

作者:天才程序YUAN

https://blog.csdn.net/JAck_chen0309/article/details/105250643

 
 
 
 
公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!
最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!

Java精选面试题(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!
------ 特别推荐 ------
特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。

点击“阅读原文”,了解更多精彩内容!文章有帮助的话,点在看,转发吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值