• java中的线程池


    前言

    在处理一些比较复杂或者费时的任务的时候,我们常常会选择多线程的方式去处理。那么怎么创建多个线程呢,当然不可能是一个一个创建的方式创建。这时候我们通常会使用线程池创建多个线程。

    线程池的优点

    1.降低资源消耗。线程池可以重复利用已创建的线程。
    2.提高响应速度。当任务到达的时候,可以不用创建,就能立即响应。
    3.提高线程的可管性。可以统一的对线程池里的线程进行统一分配,调优和监控。

    线程池的实现原理

    在这里插入图片描述
    如上图,是当一个任务来到之后,线程池的执行流程。接下来我们看下线程池的实现原理,如下图。
    在这里插入图片描述
    如图,我们可以看出,当一个线程任务到达的时候,将会放在BlockingQueue队列里,然后判断核心线程池是否满了,如果 没满,就创建线程执行任务。如果满了,就在阻塞队列里等着,当轮到自己的时候利用已有的线程执行任务.如果阻塞阻塞队列也满了.判断线程池是否满了,如果没满,就创建线程执行任务.如果满了,就执行饱和策略.
    饱和策略大致有四种,就是上图的箭头4指向的小框里面的四种.

    线程池的创建

    我们可以通过ThreadPoolExecutor来创建一个线程池.
    创建一个线程池大致需要以下几个参数(面试也会经常问)
    1.corePoolSize:核心线程池数大小,在阻塞队列没满的情况下,基本都是创建和使用核心线程池的线程,完成相应的任务.
    2.runnableTaskQueue(任务队列):用于保存等待执行任务的阻塞队列.之前我们有一个章节,专门介绍了阻塞队列,这里就不展开详细介绍.只介绍下有哪几种队列可以使用.
    (1)ArrayBlockingQueue
    (2)LinkedBlockingQueue
    (3)SynchronousQueue
    (4)PriorityBlockingQueue
    3.maximumPoolSize:线程池的允许创建的最大线程数.
    4.ThreadFactory: 用于设置创建线程的工厂.
    5.RejectedExecutionHandler(饱和策略):当线程池和队列都满的时候,需要选择一种策略来处理新提交的任务.默认是AbortPolicy,一共有四种.
    (1)AbortPolicy:直接抛出异常
    (2)CallerRunsPolicy:只用调用者所在线程来运行任务.
    (3)DiscardOldestPolicy:丢弃队列里最近一个任务,并执行当前任务.
    (4)DiscardPolicy:不处理,丢弃掉
    6.keepAliveTime:工作线程空闲后,保持存活的时间.
    7.6的时间单位.

    线程池提交任务

    线程池提交任务有两个方法:execute()和submit()
    execute用来提交不需要返回值的任务
    submit方法用于提交需要返回值的任务.线程池会返回一个fature类型的对象,通过这个fature对象可以判断任务是否执行成功,并且可以通过get方法获取返回值

    线程池的关闭

    调用线程池的shutdown或shutdownNow方法来关闭线程池
    shutdown首先将线程池的状态设置为STOP,然后尝试停止所有正在执行或暂停任务的线程,并返回等待执行任务的列表.
    shutdownNow只是将线程池的状态设置为SHUIDOWN状态,然后中断所有没有正在执行任务的线程.

    合理配置线程池

    想要合理的使用线程池,就得从任务的特性分析.
    任务性质:cpu密集型任务,io密集型任务和混合型任务
    任务优先级:高,中,低
    任务执行时间:长,中,短
    任务依赖性:是否依赖其他资源
    cpu密集型任务尽可能配置少的线程,如cpu数量加一个
    io密集型任务尽量多配置线程,因为他的线程不一定是一直在执行任务
    混合型任务:尽量将其拆分为cpu密集型任务和o密集型任务,然后按照这两种任务的处理方式处理.
    优先级任务的话,不太好处理,因为操作系统不一定任java里的优先级.但是还是可以使用优先级对列处理,会比较好.
    依赖型任务尽可能设置多的线程,例如数据库连接,可能需要等待返回结果,等待时间越长cpu空闲越长,所以线程数设置的越大越好.同时,最好使用有界对列,这样出现问题可以及时发现.

    线程池的监控

    所有的监控,基本都是获取一些主要的参数,来实现监控的目的.线程池也不例外,线程池提供了下面几个参数

    takeCount:线程池所需要执行的任务数量
    completedTaskCount:线程池在运行过程中已完成的任务数量
    largestPoolSize:线程池里曾经创建过的最大线程数量.
    getPoolSize:线程池的线程数量.
    getActiveCount:获取活动的线程数

    总结

    希望通过今天的介绍,大家都可以对线程池有一个清晰的认知.往后在用到线程池的时候,都可以正确的使用线程池应对各种场景.

  • 相关阅读:
    Rocky Linux 8.9 一键安装 Oracle 11GR2(231017)单机 ASM
    小程序图形:echarts-weixin 入门使用
    从 select、poll、epoll 回答IO多路复用
    【python】(十九)python常用第三方库——urllib3
    常见的设计模式(单例模式&工厂模式)
    14、我们仓里的年轻人
    git 分支重命名 使用IDEA进行操作
    多元联合分布建模 Copula python实例
    基于线性表的图书信息管理实验
    MySQL事务基本操作(方式2)
  • 原文地址:https://blog.csdn.net/qq_41820066/article/details/128024468