线程池基础入门

2023-11-07

线程池的状态

线程池的5种状态
RUNNING: 线程池处在 RUNNING 状态时,能够接收新任务,以及对已添加的任务进行处理。该状态是线程池的初始状态,线程池一旦被创建,就处于 RUNNING 状态
SHUTDOWN: 线程池处于 SHUTDOWN 状态时,不接收新任务,但能处理等待队列中的任务。线程池在 RUNNING 状态下,调用 shutdown() 方法,会变成 SHUTDOWN 状态。
STOP: 线程池处于 STOP 状态时,不接收新任务,不再处理等待队列中的任务,并且会中断正在处理的任务,线程池在 RUNNING 状态下,调用 shutdownNow() 方法,变为 STOP 状态
TIDYING: 所有的任务都销毁了,工作线程数量为0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()
线程池在 SHUTDOWN 状态时,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN 状态变为 TIDYING 状态;
线程池在 STOP 状态时,线程池中执行的任务为空时,就会由 STOP 状态变为 TIDYING 。
TERMINATED: terminated() 方法执行之后,线程池彻底终止,就变成 TERMINATED 状态。
在这里插入图片描述

在这里插入图片描述


ThreadPoolExecutor - 构造方法

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) 
  • corePoolSize 核心线程数(最多保留的线程数)
  • maximumPoolSize 最大线程数目
  • keepAliveTime 线程执行完任务后的空闲时间 - 针对救急线程
  • unit 时间单位 - 针对救急线程
  • workQueue 阻塞队列
  • threadFactory 线程工厂 - 可以为线程创建时起个好名字
  • handler 拒绝策略

在线程池中分为核心线程救急线程,救急线程一般是在任务阻塞队列(有界队列)满了之后才会被创建的。
corePoolSIze + 救急线程数 <= maximumPoolSize 。
救急线程存在生存时间(由keepAliveTime 决定),核心线程则没有。
当救急线程也满了(都在执行任务),如果再来一个任务,就会执行拒绝策略

Executors类和ThreadPoolExecutor都是util.concurrent并发包下面的类, Executos下面的newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor、newCachedThreadPool底层的实现都是用的ThreadPoolExecutor(构造时设置不同的参数)实现的,所以ThreadPoolExecutor更加灵活。


Executors - 固定大小的线程池

在这里插入图片描述

特点:

  • 核心线程数 = 最大线程数 (没有救急线程被创建),因此无需超时时间
  • 阻塞队列是无界的,可以放任意数量的任务

测试代码:

 public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);

        for (int i=0; i<5; i++){
            int j = i;
            fixedThreadPool.execute(()->{
                System.out.println("当前线程是"+Thread.currentThread().getName()+" --------"+j);
            });
        }

    }

执行结果:
在这里插入图片描述

适用于任务量已知,相对耗时的任务


Executors - 定时线程池

测试代码:

import java.util.concurrent.*;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);

        /**
         * 延时执行任务(执行一次)
         */
        pool.schedule(()->{
            System.out.println("延时执行任务task1");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },1,TimeUnit.SECONDS);
        pool.schedule(()->{
            System.out.println("延时执行任务task2");
        },1,TimeUnit.SECONDS);

        /**
         * 以一定的速率执行任务(执行一次)
         */
        pool.scheduleAtFixedRate(()->{
            System.out.println("以固定的速率执行------scheduleAtFixedRate");
        },1,3,TimeUnit.SECONDS);

        /**
         * 以一定的延时执行任务(执行一次)。跟固定速率不同,这个延时以上个任务结束为坐标
         */
        pool.scheduleWithFixedDelay(()->{
            System.out.println("以固定的延时执行------scheduleAtFixedRate");
        },1,3,TimeUnit.SECONDS);
    }
}

执行结果:
在这里插入图片描述


Executors - 带缓冲线程池

在这里插入图片描述

特点:

  • 核心线程数是0,最大线程数是Integer.MAX_VALUE,救急线程的空闲生存时间是60s
    • 全部都是救急线程(60s后可以回收)
    • 救急线程可以无限创建
  • 队列采用SynchronousQueue实现特点是,它没有容量(可以理解是容量为0)

整个线程池表现为线程数会根据任务量不断增加,没有上限,当任务执行完毕,空闲一分钟后释放线程。适合做任务比较密集,但每个任务执行时间较短的情况。


Executors - 单线程线程池

在这里插入图片描述
使用场景:
希望多个任务排列执行。线程数固定为1,任务数大于1,会放入无界队列排队。任务执行完毕,这个唯一的线程也不会被释放。

区别:

  • newSingleThreadExecutor与自己创建一个线程
    • 自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而线程池会新建一个线程,保证线程池的正常运行
  • newSingleThreadExecutor与newFixedThreadPool(1)
    • 【newSingleThreadExecutor】只对外暴露ExecutorService接口,一次不能调用ThreadPoolExecutor中特有的方法
    • 【newFixedThreadPool】对外暴露的是ThreadPoolExecutor对象,可以强转后调用setCorePoolSize等方法进行修改

线程池常用方法

提交任务

1、 void execute(Runnable runnable);

单纯的执行任务,没有返回结果。

ExecutorService executorService = Executors.newFixedThreadPool(2);
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("Runnable输出信息");
        }
    };
    executorService.execute(runnable);
// lamda写法
executorService.execute(()->{ System.out.println("Runnable输出信息");});

2、 Future submit(Callable task);
提交任务task,用返回值Future获取任务执行结果

ExecutorService executorService = Executors.newFixedThreadPool(2);
        Callable callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "带返回值的执行任务1";
            }
        };
        Future future1 = executorService.submit(callable);
        System.out.println(future1.get());
        // lamda写法
        Future<String> future2 = executorService.submit(() -> {
            return "带返回值的执行任务2";
        });
        System.out.println(future2.get());

3、 List<Future> invokeAll(Collection<? extends Callable> tasks)
throws InterruptedException;

提交tasks中所有的任务,接收一个集合对象(里面是Callsble对象),返回值是一个集合对象(里面是Future对象)

ExecutorService executorService = Executors.newFixedThreadPool(2);
        List<Future<Object>> futures = executorService.invokeAll(Arrays.asList(
                () -> {
                    return "invokeAll任务结果1";
                },
                () -> {
                    return "invokeAll任务结果2";
                },
                () -> {
                    return "invokeAll任务结果3";
                }
        ));
        futures.forEach(f -> {
            try {
                System.out.println(f.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });

关闭线程池

1、 shutdown()
线程池的状态变为SHUTDOWN,不会接收新的任务,但已提交的任务会执行完,此方法不会阻塞调用线程的执行
在这里插入图片描述
2、 shutdownNow()
线程池的状态变为STOP,不会接收新任务,会将队列中的任务返回,并用interrupt的方式中断正在执行的任务
在这里插入图片描述

查看线程池状态的方法

1、isShutDown()
当调用shutdown()或shutdownNow()方法后返回为true。
2、isTerminated()
当调用shutdown()方法后,并且所有提交的任务完成后,包括任务队列里面的任务返回为true。当调用shutdownNow()方法后,成功停止后返回为true。

如果线程池任务正常完成,都为false

一般可以利用shutDown()与isTerminated()来配合,实现等待线程池中的任务完成之后再去执行后面的逻辑
如下代码:

/*创建任务*/
Runnable runnable = new Runnable() {
    public void run() {
        // 执行任务xxxx
    }
};

/*创建线程池*/
ExecutorService executorService = Executors.newFixedThreadPool(10);

long end;
long start = System.currentTimeMillis();
/*执行任务*/
for (int i=0; i<100; i++) {
    executorService.execute(runnable);
}
// 关闭线程池不会接收新的任务 但已提交的任务会执行完 shutdown()此方法不会阻塞调用线程的执行
executorService.shutdown();
while (true) {
    if(executorService.isTerminated()){
         end = System.currentTimeMillis();
         break;
    }
}
System.out.println("用时"+(end-start)+"毫秒");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程池基础入门 的相关文章

  • Thread.Sleep(0)的妙用

    https www cnblogs com JianGuoWan p 9139698 html Thread Sleep 0 表示挂起0毫秒 你可能觉得没作用 你要写Thread Sleep 1000 就有感觉了 似乎毫无意义 MSDN的说
  • 2、线程池篇 - 从理论基础到具体代码示例讲解(持续更新中......)

    前言 暂无 一 线程篇 有关线程部分的知识整理请看我下面这篇博客 1 线程篇 从理论到具体代码案例最全线程知识点梳理 持续更新中 二 线程池基础知识 线程池优点 他的主要特点为 线程复用 管理线程 不需要频繁的创建和销毁线程 控制线程数量
  • ⛳ 面试题-单例模式会存在线程安全问题吗?

    目录 面试题 单例模式会存在线程安全问题吗 一 单例模式 简介 二 饿汉式 三 懒汉式 3 1 懒汉式 在调用 getInstance 的时候才创建对象 线程不安全 3 2 改造1 对懒汉式进行加锁改造 线程安全 3 3 改造2 对懒汉式继
  • 多线程之创建工作者线程和用户界面线程区别

    转帖 部分原创 1 工作者线程倾向于琐碎的处理 与它不同的是 用户界面线程具有自己的界面而且实际上类似于运行其他应用程序 创建线程而不是其他应用程序的好处是线程可与应用程序共享程序空间 这样可以简化线程与应用程序共享数据的功能 2 典型情况
  • Cpp关键字破解(三)【volatile】篇

    关键字总结 volatile 文章目录 关键字总结 volatile 0 前言 1 概念 2 作用 3 使用场景 4 volatile成员函数 5 代码体验 0 前言 参考几位前辈博客 汇总整理了一下 C 中volatile关键字的使用详解
  • 多线程实现事务回滚

    多线程实现事务回滚 特别说明CountDownLatch CountDownLatch的用法 CountDownLatch num 简单说明 主线程 mainThreadLatch await 和mainThreadLatch countD
  • java数据迁移程序

    环境 mysql 目标 亿级数据迁移 最终耗时 1 2小时 服务器更佳 建议在晚上或者没人访问的情况下操作 思路 1 不能一下将所有数据 导入到目标数据表 耗时太久 且占用资源 所有就用程序批量执行 每次执行一个范围段 比如第一个线程 1
  • WEB-7-多线程

    多线程 一 背景 二 认识线程 Thread 1 理解 2 进程和线程的区别 高频面试题 3 使用代码创建多线程 三 线程的相关操作 1 创建线程 1 方法一 继承 Thread 类 2 方法二 实现 Runnable 接口 3 其它方法
  • synchronized关键字修饰static方法和非static方法学习测试结论

    最近在学习研究synchronized关键字 发现有个疑问 在同一个类中 有多个sync方法 当线程调用其中的一个方法的时候 其他的线程能调用其他的sync方法么 为此做了简单的测试 详细的测试过程略过 读者可使用测试代码自行操作 得出结论
  • C++-std::unique_lock介绍和简单使用

    unique lock std unique lock比std lock guard更灵活 这种灵活性主要体现在以下几点 lock guard在构造时或者构造前 std adopt lock 就已经获取互斥锁 并且在作用域内保持获取锁的状态
  • 并发编程(二)——内存模型

    前言 欢迎大家一起来学习多线程 大家一起来学习吧 并发编程 一 多线程快速入门 并发编程 二 内存模型 并发编程 三 多线程之间如何实现通讯 并发编程 四 JUC并发包常用方法介绍 并发编程 五 线程池及原理剖析 并发编程 六 java中锁
  • MFC多线程编程之一——问题提出

    原文地址 http www vckbase com document viewdoc id 1704 一 问题的提出 编写一个耗时的单线程程序 新建一个基于对话框的应用程序SingleThread 在主对话框IDD SINGLETHREAD
  • python网络爬虫实战——实时抓取西刺免费代理ip

    参考网上高手示例程序 利用了多线程技术 Python版本为2 7 coding utf8 import urllib2 import re import threading import time rawProxyList checkedP
  • 55黑马QT笔记之关闭子线程

    55黑马QT笔记之关闭子线程 1 这里为什么要单独写多一篇文章来说线程的关闭呢 主要是想让大家提升印象 养成资源回收的好习惯 任何时候都要想起开辟过的内存回收 这里的关闭子线程上一篇也写到了 就是利用关闭窗口时调用槽函数回收掉 2 具体步骤
  • 阿里巴巴开发手册-并发处理

    强制 获取单例对象要线程安全 在单例对象里面做操作也要保证线程安全 说明 资源驱动类 工具类 单例工厂类都需要注意 强制 线程资源必须通过线程池提供 不允许在应用中自行显式创建线程 说明 使用线程池的好处是减少在创建和销毁线程上所花的时间以
  • iOS线程初探(四) GCD 和 NSOperation 小结

    参考资料 关于iOS多线程 看我就够了 GCD 在GCD中 有两个概念很重要 那就是任务和队列 任务 其实就是你需要做的事情 一个Block而已 任务有两种执行方式 同步执行和异步执行 同步执行 会阻塞当前线程 直至该任务执行完成后当前线程
  • JAVA并发:线程安全与Synchorinzed

    1 什么是线程安全问题 线程的合理使用能够提升程序的处理性能 主要有两个方面 第一个是能够利用多核 cpu 以及超线程技术来实现线程的并行执行 第二个是线程的异步化执行相比于同步执行来说 异步执行能够很好的优化程序的处理性能提升并发吞吐量
  • VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题...

    VC9编译的程序在没有装过VC9 确切的说是 Net Framework3 5 的机器上运行时 如果提示 由于应用程序配置不正确 应用程序未能启动 重新安装应用程序可能会纠正这个问题 这个错误 那么就说明该程序动态链接了VC9的运行时库 如
  • JUC的常见类

    目录 Callable ReentrantLock Semaphore CountDownLatch JUC 即 java util concurrent 其中存放了一些进行多线程编程时有用的类 Callable Callable是一个接口
  • 线程安全的集合类

    Java中提供了许多集合类 其中有的是线程安全的 有的是线程不安全的 线程安全的集合类有 1 Vector Vector类实现了一个 动态数组 与ArrayList相似 但Vector是同步访问的 2 Stack Stack是Vector的

随机推荐

  • 合并BPL包图文教程

    Delphi IDE 本身就是一个插件模式的工具 插件的好处不用多说 运行包的BPL 其实就是众多单元的集合 因此可以再次重新组合 只要你将各个BPL包用到的单元再组合一次 本文以 http code google com p tangra
  • libuv源码分析(1)事件循环分析

    前言 libuv总是报出一些让人难以理解的错误 作为一个C的项目 不具有Java JavaScript php那样的人气 很难百度到一些问题的答案 甚至google也不行 为了用好libuv 也为了学习吧 我开始看libuv的源码 不知道自
  • 【正点原子STM32连载】 第三十一章 睡眠模式实验 摘自【正点原子】APM32F407最小系统板使用指南

    1 实验平台 正点原子stm32f103战舰开发板V4 2 平台购买地址 https detail tmall com item htm id 609294757420 3 全套实验源码 手册 视频下载地址 http www openedv
  • 《机器学习》周志华(西瓜书)学习笔记 第二章 模型评估与选择

    机器学习 周志华 学习笔记 总目录 世上只有一种投资是只赚不赔的 那就是学习 当你的的能力还驾驭不了你的目标时 就应该沉下心来历练 当你的才华撑不起你的野心时 就应该静下心来学习 第二章 模型评估与选择 2 1 经验误差与过拟合 错误率 E
  • 11 【标准库之JSON对象 JSON5】

    13 JSON 对象 13 1 JSON 格式 JSON 格式 JavaScript Object Notation 的缩写 是一种用于数据交换的文本格式 2001年由 Douglas Crockford 提出 目的是取代繁琐笨重的 XML
  • 递归视角下

    def listSum numbers if not numbers return 0 else f rest numbers return f listSum rest myList 1 2 3 4 None total listSum
  • 在存储过程中IN传入参数无效的解决方法

    列 SELECT count COUNT sysid FROM Student WHERE Id IN Sysids 想要得到count 但是在in的时候 传入的参数无效 得到的结果只能为0 这时候可以将其转化成一条变量语句 然后去执行这条
  • websocket即时通讯

    目录 一 websocket简介 二 背景 三 优点 1 控制开销 2 实时性更强 3 保持连接状态 4 更好的二进制支持 5 支持扩展和更好的实现压缩效果 四 原理 1 客户端 服务器建立TCP连接 三次握手 2 TCP连接成功后 客户端
  • PANet[详解]

    一 Abstract摘要 Introduction介绍 Abstract 信息在神经网络中的传播方式非常重要 本文提出了一种基于提议的实例分割框架下的路径聚合网络Path Aggregation Network PANet 旨在促进信息的流
  • SQL Server 2019 Express的安装

    SQL Server 2019 Express的安装 下载安装程序 SQL Server 2019 Express 安装SQL Server 双击运行SQL2019 SSEI Expr exe 运行下载程序 选择自定义 点击安装 稍等几分钟
  • 小程序消息推送配置 Token校验失败,请检查确认

    一 小程序消息推送配置 Token校验失败 请检查确认 添加配置失败 原因 只要是没有echostr原样返回 就会报错 注意 返回的事echostr的内容 而不是key value格式 示例如下 return Content reqData
  • 大数据数据湖技术Hudi0.12.0版本源码编译

    0 介绍 Apache Hudi Hadoop Upserts Delete and Incremental 是下一代流数据湖平台 Apache Hudi将核心仓库和数据库功能直接引入数据湖 Hudi提供了表 事务 高效的upserts d
  • api的封装

    这是以 cnode中文社区的api 为例 值得一提的是有些请求可能要先进行url的编码 这是简易版的 use strict api 路径 get topics 主题首页 get topic id 主题详情 post accesstoken
  • 基于libevent, libuv和android Looper不断演进socket编程

    最近在做websocket porting的工作中 需要实现最底层socket读和写 基于同步读 libevent libuv和android Looper都写了一套 从中体会不少 1 同步阻塞读写 最开始采用同步阻塞读写 主要是为了快速实
  • 织梦网站搬迁后服务器错误,如何解决DEDECMS 5.7 将data目录迁移后网站地图无法打开和更新的问题...

    如何解决DEDECMS 5 7 将data目录迁移后网站地图无法打开和更新的问题 发布时间 2020 09 15 11 53 29 来源 亿速云 阅读 88 作者 小新 这篇文章主要介绍如何解决DEDECMS 5 7 将data目录迁移后网
  • Firefox about:config设置

    以下内容来自于转载 原文 https www jianshu com p 6e6937a9574c 地址栏输入about config 打开 搜索 书签在新标签页中打开 browser tabs loadBookmarksInTabs 默认
  • 安卓开发日志捕获,错误日志捕获catch,崩溃日志捕获,抓取崩溃日志

    import android content Context import android content SharedPreferences import android content pm PackageInfo import and
  • 从街边小吃到网上爆款,螺蛳粉是如何逆袭走红的呢?

    要说现当下最火的食物是什么 那螺蛳粉肯定占有一席之地 喝奶茶已经不是当下年轻人的续命方式了 现在只有会嗦粉的才能称得上是整条街最靓的崽 在今年五花八门的热搜中 可以说螺蛳粉长在了热搜上 从西瓜微数热搜榜来看 关于螺蛳粉的热搜可是数不胜数 在
  • windows系统升级node

    直接去官网下载对应版本的安装包 覆盖到原来的下载路径就可以了 注意一定要下载稳定版本的下载 Node js nodejs org https nodejs org zh cn download 查看node下载路径where node 查看
  • 线程池基础入门

    文章目录 线程池的状态 ThreadPoolExecutor 构造方法 Executors 固定大小的线程池 Executors 定时线程池 Executors 带缓冲线程池 Executors 单线程线程池 线程池常用方法 线程池的状态