【Java】线程池

文章目录

  • 🍆1.前言
    • 🍆1.1什么是线程池?
    • 🍆1.2为什么使用线程池?
  • 🍎2.线程池的概述
    • 🍎2.1ThreadPoolExecutor的构造组成
    • 🍎2.2**那么线程数应该设置为多少合适呢**?
    • 🍎2.3**拒绝策略**
  • 🍋3.线程池的工作流程
  • 🍐4.线程池的创建

🍆1.前言

🍆1.1什么是线程池?

线程池是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程和任务、并将线程的创建和任务的执行解耦开来。我们可以创建线程池来复用已经创建的线程来降低频繁创建和销毁线程所带来的资源消耗。在JAVA中主要是使用ThreadPoolExecutor类来创建线程池,并且JDK中也提供了Executors工厂类来创建线程池(不推荐使用)。

线程池的优点

  • 降低资源消耗,复用已创建的线程来降低创建和销毁线程的消耗。
  • 提高响应速度,任务到达时,可以不需要等待线程的创建立即执行。
  • 提高线程的可管理性,使用线程池能够统一的分配、调优和监控

🍆1.2为什么使用线程池?

我们来试想一下,没有线程池的情况下,是如何执行任务的

从上面可以看到一些缺点:

  1. 不受控制风险,为了执行一个任务创建出多个线程,这些线程无法管理
  2. 资源消耗增大,每执行一个任务都需要创建许多个线程,浪费空间,浪费时间。

🍎2.线程池的概述

🍎2.1ThreadPoolExecutor的构造组成

ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize, 
                   long keepAliveTime, 
                   TimeUnit unit, 
                   BlockingQueue<Runnable> workQueue,
                   ThreadFactory threadFactory, 
                   RejectedExecutionHandler handler)
  • corePoolSize核心线程数,只要线程池创建,就拥有corePoolSize个线程
  • maximumPoolSize最大线程数,这个线程所能拥有的最大的线程数。
  • keepAliveTime非核心线程数允许空闲的最大时间
  • unit时间单位小时–秒–毫秒
  • workQueue任务队列,线程池会提供submit方法,让其他线程把任务提交给线程池,
    线程池将任务存放到队列中,这个队列的元素是Runnable对象,执行的逻辑就是run方法里面内容。
  • threadFactory线程工厂,用于创建线程执行任务
  • handler拒绝策略,当线程池处于饱和时,使用某种策略来拒绝任务提交

🍎2.2那么线程数应该设置为多少合适呢

这不仅仅和计算机的配置有关
更重要的是与你程序的实际特点有关:

大体来说,程序可以分为
1.cpu密集型:需要大量的运算(条件判断,算术运算,函数调用)
2.IO等待型:大部分时间处于等待状态(标准的输入输出,sleep,操作硬盘,操作网络等)

对于CPU密集型来说:线程数不应该超过逻辑处理器的个数。
对于IO等待型来说:线程数的限制不在CPU上,而是与其他方面有关
如果程序是关于网络的操作,那么要根据网速来设定线程数
如果程序是操作硬盘的(输入输出)那么设置成百个线程也可以

所以,具体的线程数还是要根据具体的情况来分析,通过实验来分析找到合适的线程数。
例如设定不同的线程数,对于同一个程序,来记录程序的运行时间,和资源占用。

🍎2.3拒绝策略

ThreadPoolExecutor.AbortPolicy, 直接抛出异常
ThreadPoolExecutor.CallerRunsPolicy, 谁负责添任务,谁来执行(submit内部执行Runnable的run方法)
ThreadPoolExecutor.DiscardOldestPolicy,丢弃掉最老的任务,将最新的任务添加进来
ThreadPoolExecutor.DiscardPolicy 丢弃最新的任务

🍋3.线程池的工作流程

🍐4.线程池的创建

如下代码也是使用工厂模式来简化线程池的创建
当然也可以使用原来的版本–ThreadPoolExecutor来创建。

 //线程自动扩充,当满足不了需求时,自动创建线程。
        Executors.newCachedThreadPool();
        //创建一个拥有最多5个线程的线程池(最大线程数)
        Executors.newFixedThreadPool(5);
        //创建一个只拥有单个线程的线程池
        Executors.newSingleThreadExecutor();
        //创建一个用有10个线程,但任务延迟执行的线程池
        Executors.newScheduledThreadPool(10);

创建一个线程池的实例

    ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 1000; i++) {
            int id = i;
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello "+ id + Thread.currentThread().getName());
                }
            });
        }

说明:Executors 返回的线程池对象的弊端如下:
1) Excutors.fixedThreadPool(fixedPoolSize)和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2) Excutors.cachedThreadPool() 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

所以创建线程池时尽量采用 ThreadPoolExecutor的方法来进行创建。

以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

版权声明:本文为博主作者:爱吃南瓜的北瓜原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/2202_75795446/article/details/137862291

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2024年4月22日
下一篇 2024年4月22日

相关推荐