[JAVAee]线程池

2023-11-05

目录

线程池的作用

线程池的使用

线程池的创建方式

线程池的解析

①Executors与ThreadPoolExecutor

 ②ThreadPoolExecutor线程池的构造方法

③RejectedExecutionHandler线程池的拒绝策略

固定线程数量线程池的简单模拟实现


线程池的作用

对于线程的使用,可能会频繁的创建与销毁.

但对于这些创建与销毁来说,会产生比较大的开销.因为对于线程的创建与销毁来说,与底层的操作系统息息相关.而像进入操作系统的任务,会被称为"内核态".在内核态当中会执行其他任务,同时内核态中的操作也是我们不可控的,频繁的创建销毁线程需要的成本会更大.

对此,就有了线程池.创造了线程放入"池"中管理,并调用执行一定的任务.在任务完毕后,我们对其并不会进行销毁,而是将其放回到"池"中去.极大的减少了开销.

除了减少了资源的开销,还能对线程在"池"中进行管理.

总结:

  • 减少了资源开销,避免了线程的重复创建与销毁.
  • 增添了对于线程的管理,将线程集中放到一起能够有效的进行管理.
  • 提升了性能,任务对线程的调用响应的速度会增开,还是减少了线程的重复创建与销毁的操作.
  • 限制了线程的个数,防止其无限制的创建.

线程池的使用

在java标准库中,提供了我们使用线程池.

线程池比较特殊,不用去实例化一个类.而是调用了Executors的一个类方法(静态方法)newFixedThreadPool去创建线程池.

返回值为ExecutorService.

ExecutorService pool = Executors.newFixedThreadPool(10);//在线程池中创建10个线程
        pool.submit(new Runnable() {//调用submit方法,给线程们布置任务执行
            @Override
            public void run() {
                System.out.println("wow");
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("haha");
            }
        });

线程池的创建方式

 在Executors中线程池的创建大致分四种方法.

①newFixedThreadPool-创建固定线程数目的线程池

②newCachedThreadPool-创建线程数目动态增长的线程池

③newSingleThreadExecutor-创建单线程的线程池

④newScheduleThreadPool-创建可延迟执行命令的线程池(类似Timer)

线程池的解析

①Executors与ThreadPoolExecutor

上述对于线程池的创建的四种方法,其实本质上都是同一种方法:ThreadPoolExecutor.

Executors本质上只是对ThreadPoolExecutor类的封装.

源码:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
//在Exeucutors中实例化了一个ScheduledThreadPoolExecutor,这个类继承了ThreadPoolExecutor

可以看到都ThreadPoolExecutor这个类有关,Executors中不同种类的线程池只是在ThreadPoolExecutor传入的参数不同.

选择了要创建哪一种线程池,在Executor中会默认的帮你设定相应的参数.从而让我们更方便的使用.

 ②ThreadPoolExecutor线程池的构造方法

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corPoolSize-在线程池中的线程数目,即使线程是空闲的.除非设置了allowCoreThreadTimeOut.
  • maximumPoolSize-在线程池中允许的最大线程数目(如果线程池中的任务比较多,会暂时创建新的线程来协助完成任务.但这些新创建的线程最后是会被销毁的,所以有最大线程数=最初创建的线程数 + 临时线程数).
  • keepAliveTime-临时新创建的线程的最大空闲等待新任务的时间,如果时间一到临时创建的线程将会被销毁.
  • unit-keepAliveTime参数的时间单位.
  • workQueue-一个阻塞队列,用来管理任务.
  • threadFactory-工厂模式,辅助线程池创建线程
  • handler-线程池的拒绝策略(下文会介绍)

③RejectedExecutionHandler线程池的拒绝策略

在ThreadPoolExecutor类中,实现了四个拒绝策略

拒绝的是什么?什么时候会触发拒绝条件?

前面我们提到,通过调用创建Executors的实例化对象的submit方法将任务添加到阻塞队列当中.

当任务数量达到一定的数量,队列中塞满了或者线程池中的每一个线程都在工作没有多余的线程时会触发拒绝条件.

AbortPolicy-抛出一个RejectedExecutionException异常

CallRunsPolicy-将被拒绝的任务返回给提交任务的线程执行

DiscardOldestPolicy-抛弃阻塞队列中队首的任务,并把新任务添加进来

DiscardPolicy-抛弃这个想要新加入的任务

固定线程数量线程池的简单模拟实现

分为:

  • 有一个阻塞队列存放任务
  • 创建相应数量的线程
  • 提供一个submit方法添加任务
public class MyThreadPool extends Thread{
    private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();//阻塞队列存放任务

    public MyThreadPool(int n){//构造方法,在创建线程池的时候就创建相应数量的线程
        for(int i = 0; i < n; i++){
            Thread thread = new Thread(() -> {
                while(true){
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
        }
    }

    public void submit(Runnable runnable) throws InterruptedException {//将任务存放到阻塞队列的方法
        queue.put(runnable);
    }

    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(3);
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("wowo");
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("haha");
            }
        });
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[JAVAee]线程池 的相关文章

  • Eclipse 中的 Java 构建路径问题

    在 Eclipse 中 我有一个与我的构建路径相关的错误 错误 Project XX is missing required library middlegen 2 1 jar 但该库在构建路径配置之前被删除 是不是缓存或者其他方面有问题
  • android新手需要了解“?android:attr/actionBarSize”

    我正在经历拉尔斯 沃格尔的教程 http www vogella com articles AndroidFragments article html在使用 Fragments 时 我遇到了以下代码 android layout margi
  • Android 服务 START_STICKY START_NOT_STICKY

    我需要让我的服务始终在后台运行 并使用 startService 函数启动我的服务 无论应用程序的状态如何 我都不想重新启动服务 这是我的观察 START STICKY gt 如果应用程序启动 则服务正在重新启动 当应用程序关闭时 服务也会
  • Netbeans 雷达插件配置

    我使用的是 Netbeans 8 0 1 在提交到 SVN 之前 我需要从 IDE 运行并检查 SonarQube 分析 我已经安装了 Netbeans Radar 插件 用于启动本地分析并检查结果 这个插件有一个名为 Get Issues
  • 将 Swing 集成到简单的文本冒险游戏中

    我对 Java 中的一些中级概念相当陌生 最近 我制作了一款名为 DazzleQuest 的文本冒险游戏 它完全在开发者控制台 终端中运行 它涉及到我的朋友作为角色 所以我想向他们展示它 并通过将命令行的功能和控制台的输出转移到一个简单的
  • 在 Selenium Grid 中注册 PhantomJS 节点时出错

    我有以下问题 我成功启动了 Selenium Grid hub java jar selenium server standalone 2 53 0 jar role hub 之后我尝试使用以下命令启动 PhantomJS 节点 phant
  • Runtime.getRuntime().exec(cmd) 挂起

    我正在执行一个命令 该命令返回文件的修订号 文件名 但如果执行命令时出现问题 应用程序就会挂起 我可以做什么来避免这种情况 请在下面找到我的代码 String cmd cmd C si viewhistory fields revision
  • 如何修复运行 Android 模拟器时出现 GPU Driver Issue 错误

    我的 Android 模拟器几周前运行良好 但现在出现错误 当我运行代码时 GPU 驱动程序问题错误对话框与模拟器一起弹出 当我单击 确定 时 Android 模拟器不会按预期运行应用程序 错误如下 Your GPU driver info
  • 为什么在大多数开源java项目中局部变量没有被声明为final?

    如果我查看 OpenJDK Hibernate 或 Apache 中的 java 源代码 我还没有看到任何声明为 Final 的局部变量 这表明一些最广泛使用的 java 软件库的开发人员 不要相信final关键字可以提高可读性 不相信它会
  • Jetty 提供静态内容所需的最少文件集?

    背景 免责声明 I have veryJava 经验很少 我们之前在 Ant 构建期间使用了 Jetty 6 的包装版本来处理按需静态内容 JS CSS 图像 HTML 因此我们可以使用 PhantomJS 针对 HTTP 托管环境运行单元
  • CompletableFuture SupplyAsync

    我刚刚开始探索 Java 8 的一些并发特性 让我有点困惑的一件事是这两个静态方法 CompletableFuture
  • 不支持使用 JDK 版本“11.0.1”进行构建。请安装 JDK 版本 `1.8.0`

    我已经下载了 Visual Studio for Mac 并尝试开始学习 Xamarin iOS 和 Android 问题是当我尝试运行 android 项目时出现以下错误 Building with JDK Version 11 0 1
  • 将 JPanel 添加到 JFrame

    我有一个程序 其中将 JPanel 添加到 JFrame public class Test Test2 test new Test2 JFrame frame new JFrame Test frame setLayout new Bor
  • 在服务器上创建 Zip 文件并使用 java 下载该 zip

    我从 mkyong 获得了以下代码 用于在本地压缩文件 但是 我的要求是在服务器上压缩文件并需要下载它 任何人都可以帮忙吗 代码写入zip文件 public void zipFiles File contentFile File navFi
  • 在 x64 系统上使用 skype-java-api

    我正在使用 skype java api 在 Java 中使用 Skype 我需要的唯一功能是点击即可拨打电话号码 它在 Windows XP x86 上运行良好 但我刚刚在 Windows 7 x64 上测试它 但失败了 错误是 线程 T
  • 避免加密和编码的 URL 字符串中的换行符

    我正在尝试实现一个简单的字符串编码器来混淆 URL 字符串的某些部分 以防止它们被用户弄乱 我使用的代码几乎与示例中的相同JCA指南 http docs oracle com javase 6 docs technotes guides s
  • 如何在 Android 应用程序退出之前进行一些清理?

    当我的 Android 应用程序终止时 是否有某种 onTerminate 方法可以进行一些清理 我想清除一些 SharedPreferences 我有一个活动 它保持几个数字的运行平均值 并将其存储在 SharedPreference 中
  • 确保 MAVEN_HOME 设置正确

    这里是 Java 和 Maven 菜鸟 使用 OSX 10 8 并使用 HomeBrew 安装 Maven 1 如果我说which mvn我会得到这个 usr local bin mvn 2 如果我说echo MAVEN HOME我不会得到
  • 如何读取FTL文件中的JSONArray?

    我在我的 Java 文件中硬编码了以下 JSON 对象 JSONObject notificationInfoJson new JSONObject notificationInfoJson put title Payment Receiv
  • Java编程编译jar

    我有一个文本文件中的java源代码 必须在源代码中输入一些自定义的硬编码变量 然后将其转换为 jar 这是可行的 但是当我运行 jar 时 找不到 Main 类 当我用 WinRAR 解压 jar 文件时 我似乎找不到错误 当我通过 cmd

随机推荐

  • mysql--排序

    在项目开发时 为了使查询的数据结果满足用户的要求 通常会对查询出的数据进行上升或下降的排序 MySQL针对不同的开发需求提供两种排序的方式 分别为单字段排序和多字段排序 接下来将对这两种排序方式的语法及使用进行详细讲解 1 单字段排序 单字
  • Android 7.0新特性总结

    2016年8月22日 谷歌正式推送Android 7 0 Nougat 牛轧糖 正式版 他们还会三个月一次推送开发版 而曝光的消息看 第一个开发版就是Android 7 1 Android N主要新增了以下的新特性和优化 一 新的Notif
  • LeetCode_433. 最小基因变化

    题目链接 力扣 这道题是一道经典的BFS题型 我觉得可能会踩坑导致不能一次AC的地方有两处 一是bankSize可能为0 那么我们开辟一个记录数组的时候会报错 二是题目所说的 起始基因序列 start 默认是有效的 但是它并不一定会出现在基
  • java 多线程 总结三

    本文转载至 http blog csdn net vking wang article details 9952063 1 synchronized 把代码块声明为 synchronized 有两个重要后果 通常是指该代码具有 原子性 at
  • MYSQL--基础--06--delete删除数据,磁盘空间未释放的解决办法

    MYSQL 基础 06 delete删除数据 磁盘空间未释放的解决办法 1 原因 使用delete删除数据 不会把数据文件删除 而是将数据文件的标识位删除 因此会留下数据碎片 当有新数据写入的时候 mysql会利用这些已删除的空间再写入 如
  • MIPI D-PHY TX 一致性测试实例解析 Part 02

    如果测过1 3 x 并对这组测试的细节已经熟悉的前提下 1 4 x的测试将会变得轻松 因为几乎相同的测试项被用于时钟通道的数据测量 因此 接下来 仅着重对其中的不同点进行讨论 由于小编的工程应用中 不需要时钟工作于LP模式 因此 本章节中部
  • 点云文件的格式转换:ply转pcd,pcd转pth,查看pth格式文件

    1 ply格式转pcd格式 import open3d as o3d def convert ply to pcd ply file pcd file 读取PLY文件 point cloud o3d io read point cloud
  • jdk-jmap命令

    jmap命令详解 jmap是JVM自带的堆内存转储 heap dump 生成工具 可以用来分析某JVM进程的堆内存占用 以及所有对象的概况 其用法说明如下所示 heap 打印堆配置信息和使用概况 在Heap Configuration一节
  • 努比亚Z11系统服务器选择,努比亚Z11系统升级,赶紧来感受一下脱胎换骨的流畅感...

    原标题 努比亚Z11系统升级 赶紧来感受一下脱胎换骨的流畅感 苹果正式发布了新系统后 可当满心欢喜的果粉们在升级系统后却发现新系统中存在各式花样漏洞与BUG 而且最无法忍受的是老旧型在更新系统之后手机续航能力急速下滑 相信每个人都收到系统推
  • Kconfig内容(详细)总结附示例快速掌握

    目录 一 简介 二 内容解析 2 1 menuconfig 2 2 choice endchoice 2 3 comment 2 4 menu endmunu 2 5 if endif 2 6 source 2 7 mainmenu 2 8
  • shell 中进行算术计算的各种方法

    shell中 无法直接进行算术运算 如果直接进行算术运算会出现如下情况 1 shell中进行算术运算的各种方法 默认情况下 shell不会直接进行算术运算 而是把 算术符号 当做 字符串 与两个变量的值连接在了一起 形成了一个新的字符串 那
  • 病虫害模型算法_AI识别病虫害 在线诊断“疑难杂症”

    来源 经济日报 中国经济网 我们的产品 识农 将人工智能技术应用于农作物病虫害的诊断 识别率能达到90 以上 近日 深圳市识农智能科技有限公司CEO谢秋发在接受经济日报 中国经济网采访时表示 谢秋发介绍说 目前我们主要是聚焦于柑橘 葡萄 苹
  • [Ubuntu] [Qt] Ubuntu安装并配置Qt5.15.2环境

    1 通过清华源下载qt镜像包 官网太慢了 新版本都只能在线安装 https mirrors tuna tsinghua edu cn qt official releases online installers qt unified lin
  • mysql5.7.24-win32安装及配置

    一 Mysql安装 安装包mysql 5 7 24 win32 zip 解压该安装包 将解压后的文件夹mysql 5 7 24 win32放到C盘根目录下 置mysql环境变量 系统变量 新建 变量名为MYSQL HOME 变量值为C my
  • java无重复字符的最长子串

    给定一个字符串 s 请你找出其中不含有重复字符的 最长子串 的长度 示例 1 输入 s abcabcbb 输出 3 解释 因为无重复字符的最长子串是 abc 所以其长度为 3 示例 2 输入 s bbbbb 输出 1 解释 因为无重复字符的
  • 如何用java实现增删改查

    使用Java实现增删改查操作需要连接数据库 例如使用JDBC或者其他ORM框架 下面是一个简单的例子 展示如何使用Java和JDBC进行增删改查操作 导入JDBC驱动程序 在Java项目中 需要将相应的JDBC驱动程序添加到项目的依赖中 建
  • qt-两个界面传值交互

    一 说明 A 子界面 B 主界面 实现A往B传值 B显示 二 利用emit和slot实现 2 1 对A h 添加声明 signals void sendData QString 用来传递数据的信号 2 2在A cpp中适当位置将数据进行发射
  • JDK1.8和JDK8是同一个版本吗?

    是的 JDK1 8和JDK8是同一个版本 最开始 命名为 JDK1 JDK2 后来就 命名为 JDK1 7 JDK1 8 Java Development Kit JDK 是Sun公司 已被Oracle收购 针对Java开发员的软件开发工具
  • 一个简单的Mysql查询

    最近工作上遇到一个 神奇 的问题 或许对大家有帮助 因此形成本文 问题大概是 我有两个表 TableA TableB 其中 TableA 表大概百万行级别 存量业务数据 TableB 表几行 新业务场景 数据还未膨胀起来 image 语义上
  • [JAVAee]线程池

    目录 线程池的作用 线程池的使用 线程池的创建方式 线程池的解析 Executors与ThreadPoolExecutor ThreadPoolExecutor线程池的构造方法 RejectedExecutionHandler线程池的拒绝策