• 线程池的基本概念


    线程池

    前言

    平时讨论多线程处理,一定会说使用线程池,那为什么要使用线程池呢?其实,这个问题也可以反过来思考一下,如果不使用线程池会怎么样?

    当需要多线程并发执行任务时,只能不断的通过new Thread创建线程,每创建一个线程都需要在堆上分配内存空间,同时需要分配虚拟机栈,本地方法栈,程序计数器等线程私有的内存空间,当这个线程对象被可达性分析算法标记为不可用时,被GC回收,这样频繁的创建和回收需要大量的额外开销。再者说,JVM的内存资源是有限的,如果系统中大量的创建线程对象,JVM很可能直接抛出OutOfMemoryError异常,还有大量的线程去竞争CPU会产生其他的性能开销,更多的线程反而会降低性能,所以必须要限制线程数。

    既然不使用线程池会有那么多问题,我们来看一下使用线程池有哪些好处:

    1.使用线程池可以复用池中的线索,不需要每次都创建新线程,减少创建和销毁线程的开销。

    2.同时,线程池具有队列缓冲策略,拒绝机制和动态管理线程个数,特定的线程池还具有定时执行,周期执行功能,比较重要的一点是线程池可以实现线程环境的隔离,例如分别定义支付功能相关线程池和优惠券功能相关线程池,当其中一个运行有问题时不会影响另一个。

    一个线程池里面有多个线程,因此我们后续都是用线程池对象的方法进行多线程操作的,这样我们只针对线程池对象就行了,不必再针对线程对象了,因此我们就不用频繁的创建销毁线程了。

    线程池的类结构图

    如下图:

    在这里插入图片描述

    线程池状态

    Running:线程池运行状态

    Shutdown状态:线程池不会再接收新的任务,但会处理阻塞队列剩余任务

    Stop状态:会中断正在执行的任务,并抛弃阻塞队列任务

    Tidying状态:任务全部执行完毕,活动线程为0即将进入终结

    Terminated状态:终结状态。

    ThreadPoolExecutor构造方法

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    corePoolSize 核心线程数目,最多保留的线程数

    maximumPoolSize 最大线程数目

    keepAliveTime 生存时间-针对救急线程

    unit 时间单位-针对救急线程

    workQueue 阻塞队列

    threadFactory 线程工厂-可以为线程创建时起个好名字

    handler 拒绝策略

    在这里插入图片描述

    最大线程数=核心线程数+救急线程数,其中核心线程不会消失永远存在,而救急线程是会消失的。

    使用newFixedThreadPool方法给线程池创建固定线程数

    newFixedThreadPool方法可以在线程池里面创建固定的线程个数,如下图:

    在这里插入图片描述

    当我们调用我们的线程池执行一个任务的时候,线程池会调用它里面的线程此任务,如下图:

    在这里插入图片描述

    提交任务方法submit

    //执行任务
    void execute(Runnable command);
    
    //提交任务task,用返回值Future获得任务执行结果
    <T> Future<T> submit(Callable<T> task);
    
    //提交tasks中所有任务
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    
    //提交tasks中所有任务,带超时时间
    <T> List<Future<T>> invokeAll(Collection<? extend Callable<T>> tasks,
                                 long timeout,TimeUnit unit)
        throws InterruptedException;
    
    //提交tasks中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其他任务取消
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    
    //提交tasks中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其他任务取消,带超时时间
    <T> T invokeAny(Collection<>? extends Callable<T>> tasks,
                   long timeout,TimeUnit unit)
        throws InterruptedException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    当我们使用submit给线程池提交任务的时候,线程池会用它里面的不同的线程去并发执行这些任务,如下图:

    在这里插入图片描述

    submit方法提交任务的时候,有两种类型的参数,一种是Callable线程任务,这种任务有返回值并且可以内部抛异常,另外一种是Runnable线程任务,这种任务没有返回值并且不可以在内部抛异常。但是Callable和Runnable对象都属于是多线程任务对象。Callable线程对象对应的线程方法是call方法,而Runnable线程对象对应的方法是run方法。

    对于任务来讲,只要它一提交到线程池里面,它就会被自动的用线程池里面的线程执行了。

    使用submit提交的线程任务,一般会在下面的普通代码执行之后执行,如下图:

    在这里插入图片描述

    关闭线程池方法shutdown

    /**
    	线程池状态变为 shutdown
    	不会接收新任务
    	但已提交的任务会执行完
    	此方法不会阻塞调用线程的执行
    */
    void shutdown();
    
    /**
    	线程池状态变为stop
    	不会接收新任务
    	会将队列中的任务返回
    	并用interrupt的方式中断正在执行的任务
    */
    List<Runnable> shutdownNow();
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    创建多线程的几个方法

    直接继承Thread

    在这里插入图片描述

    实现Runnable接口

    在这里插入图片描述

    实现Callable接口

    在这里插入图片描述

    jdk1.8新增线程池

    在这里插入图片描述

    使用偷窃线程池的时候,线程池中的每个线程都有一个任务队列,线程之前可以互相帮助,如果一个线程的工作已经干完了,发现另外一个线程的工作还没有干完,那么这个线程会去帮另外一个线程工作。这个线程池非常适合于耗时较长的任务。

  • 相关阅读:
    图匹配(Graph Matching)入门学习笔记——以《Factorized Graph Matching》为例(三)
    oracle数据库导入导出
    java 版本企业招标投标管理系统源码+多个行业+tbms+及时准确+全程电子化
    ACM. HJ70 矩阵乘法计算量估算 ●●
    The list of sources could not be read
    给按钮的边框和文字设置不同的背景色
    离散数学_十章-图 ( 6 ):欧拉通路与哈密顿通路
    VScode开发ARM环境搭建
    聊聊RNN&LSTM
    AM@导数和微分的应用@弧微分和曲率
  • 原文地址:https://blog.csdn.net/qq_45950109/article/details/124881758