当前位置:首页 > 科技  > 软件

阿里规范竟然不让我用这种方式创建线程池

来源: 责编: 时间:2023-10-06 19:21:33 212观看
导读今天我们来聊一下这个 Java 中的线程池,线程池,这块的内容,已经是非常的容易被面试官问到的内容,为什么呢?这是因为线程池,是一种多线程的处理方式,如果使用方式得当的话,那么对我们的代码的质量也是非常高的。我们既然要了解

今天我们来聊一下这个 Java 中的线程池,线程池,这块的内容,已经是非常的容易被面试官问到的内容,为什么呢?这是因为线程池,是一种多线程的处理方式,如果使用方式得当的话,那么对我们的代码的质量也是非常高的。JwH28资讯网——每日最新资讯28at.com

我们既然要了解线程池,那么肯定是需要从几个角度来考虑,第一,什么是线程池?第二:为什么需要线程池?第三,线程池的创建方式都有哪些。JwH28资讯网——每日最新资讯28at.com

什么是线程池

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。JwH28资讯网——每日最新资讯28at.com

线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元 中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所 有处理器保持繁忙。JwH28资讯网——每日最新资讯28at.com

如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。JwH28资讯网——每日最新资讯28at.com

为什么需要线程池

我们有两种常见的创建线程的方法,JwH28资讯网——每日最新资讯28at.com

  • 一种是继承Thread类,
  • 一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口。

但是我们创建这两种线程在运行结束后都会被虚拟机销毁,如果线程数量多的话,频繁的创建和销毁线程会大大浪费时间和效率,更重要的是浪费内存。那么有没有一种方法能让线程运行完后不立即销毁,而是让线程重复使用,继续执行其他的任务哪?JwH28资讯网——每日最新资讯28at.com

这就是线程池的由来,很好的解决线程的重复利用,避免重复开销。JwH28资讯网——每日最新资讯28at.com

线程池的优点都有哪些?

(1)重用存在的线程,减少对象创建销毁的开销。JwH28资讯网——每日最新资讯28at.com

(2)可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。JwH28资讯网——每日最新资讯28at.com

(3)提供定时执行、定期执行、单线程、并发数控制等功能。JwH28资讯网——每日最新资讯28at.com

而且优点这么多,那么肯定就得知道 Java 提供了哪些线程池的实现方式了。JwH28资讯网——每日最新资讯28at.com

Java 提供了哪几种线程池

种类一

FixedThreadPoolJwH28资讯网——每日最新资讯28at.com

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

newFixedThreadPool 实际上返回的是 ThreadPoolExecutor,ThreadPoolExecutor 实际就是线程池实现类,使用了典型的模板方法设计模式,通过ThreadPoolExecutor构造器的说明我们稍微解释一下各参数的意思:JwH28资讯网——每日最新资讯28at.com

构造器如下:JwH28资讯网——每日最新资讯28at.com

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue) {        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,             Executors.defaultThreadFactory(), defaultHandler);    }
  • corePoolSize 核心线程数,线程池一直存在的线程(即使这些线程是空闲的),除非你设置allowCoreThreadTimeOut
  • maximumPoolSize 线程池中允许存在的最多的线程数,当workQueue满了之后会创建线程直到数量达到maximumPoolSize
  • keepAliveTime 当线程池中的线程数超过核心线程数,超过部分的线程可以空闲keepAliveTime时间,如果这段时间还没有任务过来则超过部分线程就会销毁
  • unit keepAliveTime的单位
  • workQueue 等待队列,当corePoolSize线程都在处理任务时,新进入线程池的任务则翻入等待下队列
  • threadFactory 创建线程池中线程的线程工厂
  • handler 拒绝策略 当线程池已达到最大线程数和等待队列也已经满了,则使用拒绝策略

而newFixedThreadPool使用了corePoolSize和maximumPoolSize相等,所以当线程池线程数到达corePoolSize之后就不会再创建线程。JwH28资讯网——每日最新资讯28at.com

并且newFixedThreadPool使用了LinkedBlockingQueue,而且使用的是默认构造器,容量是Integer.MAX_VALUE,keepAliveTime是0,实际上设不设置都没关系,因为不会超过核心线程数。JwH28资讯网——每日最新资讯28at.com

实际上我们也可以理解为FixedThreadPool该线程池中的线程数量始不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。JwH28资讯网——每日最新资讯28at.com

种类二

SingleThreadExecutorJwH28资讯网——每日最新资讯28at.com

实际上SingleThreadExecutor是使用单个 worker 线程的Executor。JwH28资讯网——每日最新资讯28at.com

也就是说方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程 池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务JwH28资讯网——每日最新资讯28at.com

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

SingleThreadExecutor 的 corePoolSize 和 maximumPoolSize 被设置为 1 。其他参数与 FixedThreadPool 相同。 SingleThreadExecutor 使用无 队列 LinkedBlockingQueue 作 为线程池的工作队列( 队列的容量为Integer.MAX_VALUE )。JwH28资讯网——每日最新资讯28at.com

种类三

CachedThreadPoolJwH28资讯网——每日最新资讯28at.com

该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数 量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新 的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复 用。JwH28资讯网——每日最新资讯28at.com

public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                      60L, TimeUnit.SECONDS,                                      new SynchronousQueue<Runnable>());    }
  • 这个线程池corePoolSize是0,maximumPoolSize是Integer.MAX_VALUE,根据我们之前对源码的分析,CachedThreadPool不会有核心线程,核心线程数的addworker方法不会执行,直接尝试加入queue中。
  • keepAliveTime是60s,也就是60s从队列中没有拿到任务,worker就会自动销毁。
  • queue使用的是SynchronousQueue,这个就是CachedThreadPool实现不停创建工作线程的关键,因为线程池处理任务分为三步:有任务过来先创建核心线程,当线程数达到核心线程数时则会进入等待队列,当等待队列满了则再创建非核心线程,直到线程数达到最大线程数后执行拒绝策略,所以可以猜测SynchronousQueue应该是没有容量的队列,放入一个offer操作必须有一个poll操作在等待,没有的话就执行入队失败,然后创建非核心线程进行处理
  • 线程工厂和拒绝策略都没有指定,则使用的就是默认的,默认的拒绝策略是丢出一个异常

种类四

ScheduledThreadPoolExecutorJwH28资讯网——每日最新资讯28at.com

这个线程池的构造器就比较多了JwH28资讯网——每日最新资讯28at.com

// 第一个构造函数   public ScheduledThreadPoolExecutor(int corePoolSize) {       super(corePoolSize, Integer.MAX_VALUE,             DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,             new DelayedWorkQueue());   }   // 第二个构造函数   public ScheduledThreadPoolExecutor(int corePoolSize,                                      ThreadFactory threadFactory) {       super(corePoolSize, Integer.MAX_VALUE,             DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,             new DelayedWorkQueue(), threadFactory);   }   // 第三个构造函数   public ScheduledThreadPoolExecutor(int corePoolSize,                                      RejectedExecutionHandler handler) {       super(corePoolSize, Integer.MAX_VALUE,             DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,             new DelayedWorkQueue(), handler);   }   // 第四个构造函数   public ScheduledThreadPoolExecutor(int corePoolSize,                                      ThreadFactory threadFactory,                                      RejectedExecutionHandler handler) {       super(corePoolSize, Integer.MAX_VALUE,             DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,             new DelayedWorkQueue(), threadFactory, handler);   }

主要用来在给定的延迟后运行任务,或者定期执行任务。ScheduledThreadPoolExecutor又分为:ScheduledThreadPoolExecutor(包含多个线程)和SingleThreadScheduledExecutor (只包含一个线程)两种。JwH28资讯网——每日最新资讯28at.com

线程池的创建方式

其实创建方式,就是Executors,使用 Executors 可以非常轻易的创建我们上面所说的这几种线程池。但是呢,有一个地方不知道大家有没有注意到,在 阿里的开发手册上面,是不允许使用 Executors 去创建的,更推荐我们使用的是 ThreadPoolExecutor 构造去创建,这样的好处就是为了规避资源耗尽的风险那时候抛出的就不是异常,而是错误了。JwH28资讯网——每日最新资讯28at.com

使用ThreadPoolExecutor的构造函数创建

private static ExecutorService executor = new ThreadPoolExecutor(13, 13,60L, TimeUnit.SECONDS,new ArrayBlockingQueue(13));

我们可以自己直接调用 ThreadPoolExecutor 的构造函数来自己创建线程池。在创建的同时,给 BlockQueue 指定容量就可以了。JwH28资讯网——每日最新资讯28at.com

这时候如果提交的线程数超过了可用线程数的时候,就会抛出异常,比如 java.util.concurrent.RejectedExecutionException,这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。JwH28资讯网——每日最新资讯28at.com

如果你觉得对 Error 和 Exception 没有任何感觉得话,你也是可以使用 Executors 去创建的。JwH28资讯网——每日最新资讯28at.com

你还知道有其他方式去创建线程池的么?JwH28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-12172-0.html阿里规范竟然不让我用这种方式创建线程池

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 我们一起聊一聊Not only Java

下一篇: Python 中的真与假

标签:
  • 热门焦点
  • Mate60手机壳曝光 致敬自己的经典设计

    Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • vivo TWS Air开箱体验:真轻 臻好听

    vivo TWS Air开箱体验:真轻 臻好听

    在vivo S15系列新机的发布会上,vivo的最新款真无线蓝牙耳机vivo TWS Air也一同发布,本次就这款耳机新品给大家带来一个简单的分享。外包装盒上,vivo TWS Air保持了vivo自家产
  • 2023年Q2用户偏好榜:12+256G版本成新主流

    2023年Q2用户偏好榜:12+256G版本成新主流

    3月份的性能榜、性价比榜和好评榜之后,就要轮到2023年的第二季度偏好榜了,上半年的新机潮已经过去,最明显的肯定就是大内存和存储的机型了,另外部分中端机也取消了屏幕塑料支架
  • 8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月5日消息,据灯塔专业版数据,截至8月5日9时35分,8月总票房(含预售)已突破10亿。其中,《封神》以大比分的优势领先。根据官方消息,目前该片总票房已经超过14.
  • 把LangChain跑起来的三个方法

    把LangChain跑起来的三个方法

    使用LangChain开发LLM应用时,需要机器进行GLM部署,好多同学第一步就被劝退了,那么如何绕过这个步骤先学习LLM模型的应用,对Langchain进行快速上手?本片讲解3个把LangChain跑起来
  • 零售大模型“干中学”,攀爬数字化珠峰

    零售大模型“干中学”,攀爬数字化珠峰

    文/侯煜编辑/cc来源/华尔街科技眼对于绝大多数登山爱好者而言,攀爬珠穆朗玛峰可谓终极目标。攀登珠峰的商业路线有两条,一是尼泊尔境内的南坡路线,一是中国境内的北坡路线。相
  • 最“俊美”淘宝卖家,靠直播和短视频圈粉,上架秒光,年销3000万

    最“俊美”淘宝卖家,靠直播和短视频圈粉,上架秒光,年销3000万

    来源 | 电商在线文|易琬玉编辑|斯问受访店铺:Ringdoll戒之人形图源:微博@御座的黄山、&ldquo;Ringdoll戒之人形&rdquo;淘宝店铺有关外貌的评价,黄山已经听累了。生于1985年的他,哪
  • 腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    作者:无锈钵来源:财经无忌7月16日晚,上海1862时尚艺术中心。伴随着幻象的精准命中,硕大的荧幕之上,比分被定格在了14:12,被寄予厚望的EDG战队以绝对的优势战胜了BLG战队,拿下了总决
  • 电博会上海尔智家模拟500平大平层,还原生活空间沉浸式体验

    电博会上海尔智家模拟500平大平层,还原生活空间沉浸式体验

    电博会为了更好地让参展观众真正感受到智能家居的绝妙之处,海尔智家的程传岭先生同样介绍了展会上海尔智家的模拟500平大平层,还原生活空间沉浸式体验。程传
Top
Baidu
map