JAVA线程池——ThreadPool

前言

线程的使用在 Java 开发中已经屡见不鲜了,在并发编程,分布式的场景中更是常客,但是对于线程的使用可能一些职场新人还是会有些不熟悉,结合池化技术的线程池也可能尚未有了解,今天这篇我们就先来说一些Java线程池中的一些基本知识以及原理。

线程池ThreadPool

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。他的主要特点为:线程复用;控制最大并发数;管理线程。

线程池工作流程

  1. 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
  2. 当调用 execute() 方法添加一个任务时,线程池会做如下判断:
    a) 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
    b) 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
    c) 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
    d) 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常RejectExecutionException。
  3. 当一个线程完成任务时,它会从队列中取下一个任务来执行。
  4. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
    在这里插入图片描述

线程池参数

老规矩,上代码,下面是ThreadPoolExector的构造函数:

	public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  1. int corePoolSize 核心线程数
  2. int maximumPoolSize 最大线程数
  3. long keepAliveTime 当前线程池数量超过corePoolSize时,多余的空闲线程的存活时间,即多次时间内会被销毁
  4. TimeUnit unit 时间单位
  5. BlockingQueue workQueue 任务队列,被提交但尚未被执行的任务
  6. ThreadFactory threadFactory 线程工厂,一般用默认的就好了
  7. RejectedExecutionHandler handler 拒绝策略,当任务太多来不及处理,如何拒绝任务

拒绝策略

线程池中的线程已经用完了,无法继续为新任务服务,同时,等待队列也已经排满了,再也塞不下新任务了。这时候我们就需要拒绝策略机制合理的处理这个问题。 JDK内置的拒绝策略如下:

  1. AbortPolicy : 直接抛出异常,阻止系统正常运行。
  2. CallerRunsPolicy : 只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。显然这样做不会真的丢弃任务,但是,任务提交线程的性能极有可能会急剧下降。
  3. DiscardOldestPolicy : 丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再次提交当前任务。
  4. DiscardPolicy : 该策略默默地丢弃无法处理的任务,不予任何处理。如果允许任务丢失,这是最好的一种方案。

以上内置拒绝策略均实现了RejectedExecutionHandler接口,若以上策略仍无法满足实际需要,完全可以自己扩展RejectedExecutionHandler接口

JDK8自带线程池

newSingleThreadPool

这个线程池只有一个核心线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

  • corePoolSize : 1,只有一个核心线程在工作
  • maximumPoolSize : 1
  • keepAliveTime : 0L
  • workQueue : new LinkedBlockingQueue(),无界缓冲队列

newScheduledThreadPool

newScheduledThreadPool是核心线程池固定,大小无限的线程池,此线程池支持定时以及周期性执行任务的需求,创建一个周期性执行任务的线程池。如果闲置,非核心线程池会在DEFAULT_KEEPALIVEMILLIS时间内回收

  • corePoolSize : corePoolSize
  • maximumPoolSize : Integer.MAX_VALUE
  • keepAliveTime : DEFAULT_KEEPALIVE_MILLIS
  • workQueue : new DelayedWorkQueue<>()

newFixedThreadPool

newFixedThreadPool是固定大小的线程池,只有核心线程,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。多数针对一些很稳定很固定的正规并发线程,多用于服务器。

  • corePoolSize : nThreads
  • maximumPoolSize : nThreads
  • keepAliveTime : 0L
  • workQueue : new LinkedBlockingQueue(),无界缓冲队列

newCacheThreadPool

这个是无界线程池,如果线程池大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)线程,当任务数增加时,此线程池又可以智能地添加新线程来处理任务。
线程池大小完全依赖于操作系统能够创建的最大线程大小。SynchronousQueue是一个缓冲区为1的阻塞队列。
缓存型池子通常用于执行一些生存期很短的异步型任务,因此在一些面向连接的daemon型Server中用得不多,但对于生存期短的异步任务,它是Executor的首选。

  • corePoolSize : 0
  • maximumPoolSize : Integer.MAX_VALUE
  • keepAliveTime : 60L
  • workQueue : new SynchronousQueue(),缓冲区为1的阻塞队列

By the way

有问题?可以给我留言或私聊
有收获?那就顺手点个赞呗~

当然,也可以到我的公众号下「6曦轩」,输入“学习”,即可领取一份
【Java工程师进阶架构师的视频教程】~
在这里插入图片描述
由于我咧,科班出身的程序员,php,Android以及硬件方面都做过,不过最后还是选择专注于做 Java,所以有啥问题可以到公众号提问讨论(技术情感倾诉都可以哈哈哈),看到的话会尽快回复,希望可以跟大家共同学习进步,关于服务端架构,Java 核心知识解析,职业生涯,面试总结等文章会不定期坚持推送输出,欢迎大家关注~~~

发布了29 篇原创文章 · 获赞 9 · 访问量 9949

猜你喜欢

转载自blog.csdn.net/weixin_42669785/article/details/102755080