java的线程池-ExecutorService

ExecutorService详解:Java 17线程池管理从零到一 本文深度解析Java 17中ExecutorService线程池管理技术,涵盖线程池核心概念、参数配置、拒绝策略、动态调整及企业级实战案例。通过代码示例详解FixedThreadPool、CachedThreadPool等类型选择,结合监控指标与调优策略,帮助开发者构建高性能、可扩展的并发架构,解决资源竞争与系统过载问题。 阅读详情

ExecutorService

继承树

ExecutorService是java对线程池定义的一个接口,也是java默认给我们的,它具有两个实现类:

  1. ThreadPoolExecutor
  2. ScheduledThreadPoolExecutor

ExecutorService继承了Executor接口,这个接口只有一个excute()方法,这里我们展示一下它们的类图:

在这里插入图片描述

原理

一般在实际业务中,我们对于线程的使用都是比较频繁的,但是线程之间的切换是非常消耗cpu的,所以我们会使用线程池,也就是java提前创建好了许多线程,利用可回收的池化的概念,来完成对线程池的优化的工作。

相关参数

ThreadPoolExecutor参数

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数
  • keepAliveTime:线程最大空闲时间
  • TimeUnit:时间单位
  • workQuene:线程等待队列
  • threasFactory:线程创建工厂
  • RejectedExecutionHander:拒绝策略
corePoolSize、maximumPoolSize、RejectedExecutionHander
  • corePoolSize、maximumPoolSize控制了线程的创建数量,corePoolSize定义了核心线程的数量,maximumPoolSize定义了当前线程池的最大线程数量,RejectedExecutionHander定义了拒绝的策略。
  • 三者关系:当线程的创建的数量<corePoolSize的时候,无论当前线程是否空闲,当有新的任务加入的时候都会新建一个线程,但是当线程池的创建数量≥corePoolSize的时候,新的任务出现如果是有空闲线程就会重用空闲线程,如果没有空闲的线程就会新建一个线程;当线程的数量≥maximumPoolSize的时候,多余的线程就会进入到排队中,当排队的数量过多的时候,在实际业务中我们机会执行拒绝策略。
keepAliveTime、TimeUnit
  • keepAliveTime是线程空闲的时间、TimeUnit是时间的单位,这两个的组合,才可以定义一个完整的时间。
  • 这个时间用来处理线程回收,超过这个时间的线程会被回收,但是默认对于核心线程是无效的,只有通过设置才可以实现对核心线程有效。
workQuene

线程等待队列,主要是用来存放提交的任务。

RejectedExecutionHander

拒绝策略,当线程池被关闭或者线程池的线程满了而且队列也满了才会启动拒绝策略。

创建ExecutorService

java给我们提供了Executors工厂类,可以帮助我们创建各种类型的ExecutorService线程池,如下四种:

1. newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

这里值得注意的是,Executors只是一个工厂类,它所有的方法返回的都是ThreadPoolExecutor、ScheduledThreadPoolExecutor这两个类的实例。

使用ExecutorService

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

executorService.shutdown();

执行ExecutorService

ExecutorService的执行方法有四种

- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(...)
- invokeAll(...)

execute(Runnable)

这个方法可以接受一个runnable实例,并且异步执行,但是这个方法没有办法知道task的执行结果:

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
public void run() {
    System.out.println("Asynchronous task");
}
});

executorService.shutdown();

submit(Runnable)

submit(Runnable)也是接收一个runnable实例,不同的是,这个方法可以返回一个Future对象,通过返回的Future对象,我们可以检查提交的任务是否执行完成:

ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(new Runnable() {
            public void run() {
                System.out.println("Asynchronous task");
            }
        });

        System.out.println(future.get());//如果这里返回一个null,表示任务执行完毕,这个方法会产生阻塞。

submit(Callable)

这个方法接收的是Callable实例,然后也会返回一个Future对象。除此之外,因为这个方法接收的是Callable接口的一个实例,这个接口会有一个call()方法的返回值,可以返回任务的执行结果。

 ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(new Callable(){
            public Object call() throws Exception {
                System.out.println("Asynchronous Callable");
                return "Callable Result";
            }
        });

        System.out.println("future.get() = " + future.get());

如果任务执行完成,future.get()方法会返回Callable任务的执行结果。注意,future.get()方法会产生阻塞。

invokeAny(Callable)

invokeAny(Callable)接收一个Callable集合,执行的方法不会返回一个Future,但是会返回所有的callable任务中其中一个任务的执行结果,但是不能保证返回的是哪一个执行的结果,反正就是其中一个。

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
    return "Task 3";
}
});

String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();

invokeAll(Callable)

invokeAll(Callable)也是接收一个Callable集合,然后返回一个Future的list,对应每一个任务执行后的Future对象

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 1";
}
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
    return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
    return "Task 3";
}
});

List<Future<String>> futures = executorService.invokeAll(callables);

for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}

executorService.shutdown();

关闭ExecutorService

  • 当我们使用完成ExecutorService之后应该关闭它,否则它里面的线程会一直处于运行状态。

  • 举个例子,如果的应用程序是通过main()方法启动的,在这个main()退出之后,如果应用程序中的ExecutorService没有关闭,这个应用将一直运行。之所以会出现这种情况,是因为ExecutorService中运行的线程会阻止JVM关闭。

  • 如果要关闭ExecutorService中执行的线程,我们可以调用ExecutorService.shutdown()方法。在调用shutdown()方法之后,ExecutorService不会立即关闭,但是它不再接收新的任务,直到当前所有线程执行完成才会关闭,所有在shutdown()执行之前提交的任务都会被执行。

  • 如果我们想立即关闭ExecutorService,我们可以调用ExecutorService.shutdownNow()方法。这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。但是它并不对正在执行的任务做任何保证,有可能它们都会停止,也有可能执行完成。

使用RunTime.getRunTime().addShutdownHook优雅关闭线程池

  • 有时候我们用到的程序不一定总是在JVM里面驻守,可能调用完就不用了,释放资源.

  • RunTime.getRunTime().addShutdownHook的作用就是在JVM销毁前执行的一个线程.当然这个线程依然要自己写.

  • 利用这个性质,如果我们之前定义了一系列的线程池供程序本身使用,那么就可以在这个最后执行的线程中把这些线程池优雅的关闭掉.

比如我们定义了一个线程池

private ExecutorService streamThreadPool = Executors.newFixedThreadPool(streamNum);

我们对它优雅的关闭

Runtime.getRuntime().addShutdownHook(new Thread() {
   public void run() {
      shutdownGracefully();
   }
});
public void shutdownGracefully() {
   shutdownThreadPool(streamThreadPool, "main-pool");
}

/**
 * 优雅关闭线程池
 * @param threadPool
 * @param alias
 */
private void shutdownThreadPool(ExecutorService threadPool, String alias) {
   log.info("Start to shutdown the thead pool: {}", alias);

   threadPool.shutdown(); // 使新任务无法提交.
   try {
      // 等待未完成任务结束
      if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
         threadPool.shutdownNow(); // 取消当前执行的任务
         log.warn("Interrupt the worker, which may cause some task inconsistent. Please check the biz logs.");

         // 等待任务取消的响应
         if (!threadPool.awaitTermination(60, TimeUnit.SECONDS))
            log.error("Thread pool can't be shutdown even with interrupting worker threads, which may cause some task inconsistent. Please check the biz logs.");
      }
   } catch (InterruptedException ie) {
      // 重新取消当前线程进行中断
      threadPool.shutdownNow();
      log.error("The current server thread is interrupted when it is trying to stop the worker threads. This may leave an inconcistent state. Please check the biz logs.");

      // 保留中断状态
      Thread.currentThread().interrupt();
   }

   log.info("Finally shutdown the thead pool: {}", alias);
}
Java中ExecutorService线程池的使用(Runnable和Callable多线程实现) 线程的创建和释放,需要占用不小的内存和资源。如果每次需要使用线程时,都new 一个Thread的话,难免会造成资源的浪费,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪。不利于扩展,比如如定时执行、定期执行、线程中断,所以很有必要了解下ExecutorService的使用。ExecutorService是Java提供的线程池,也就是说,每次我们需要使用线程的时候,可以通过ExecutorService获得线程。... 阅读详情

相关推荐

线程池ExecutorService空闲线程的个数

keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但...

Top5软件工程硕士,先后在京东、字节从事多年Java后端开发、实时和离线大数据开发 2万+

java 调用其他线程_java 后台接口另起一个线程执行其他业务

直接post代码,然后在详细介绍为什么:packagecom.xxx.testset.service.impl;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/**** @function xxx接口实现类*@authorLiangjw* @date 2019-9-18 下午02:...

weixin_39986060的博客 1217

【机器人】线性方程最小二乘解法对机械臂DH参数进行标定

1.前言 看了一篇文章,觉得里面的DH参数标定法讲的很清晰,便使用Matlab复现了一下,效果还可以,特写此文记录。 2.原理 2.1.误差最佳值的最小二乘计算 有研究结果表明:几乎95%的机器人位置误差都是由机器人内部运动学的不准确描述引起的,所以对DH模型参数进行标定是很有必要的。 DH参数物理含义:选自《机器人学、机器视觉与控制-Matlab基础》 当DH参数确定后,我们...

要恰饭得嘛 1万+

Java线程池 ExecutorService

一、ExecutorService介绍 ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法: Java API对ExecutorService接口的实现有两个,所以这两个即是Java线程池具体实现类: ThreadPoolExecutor ScheduledThreadPoolExecutor ExecutorService还继承了Executor接口(注意区分Executor接口和Execu

qq_40056060的博客 5844

直线型一阶倒立摆1---从理论到实践的桥梁

本文深入探讨了直线型一阶倒立摆在控制理论中的核心地位,从非线性控制、鲁棒性到实时反馈等关键问题。通过实际案例和硬件搭建指南,帮助读者理解从理论到实践的过渡,特别适合控制工程初学者和研究人员。文章还提供了算法选型建议和硬件避坑手册,是掌握倒立摆控制的实用指南。

weixin_29047545的博客 317

ADS新手必看:ICCAP数据导入与导出CSV的完整流程(附常见问题解决)

本文为ADS新手详细讲解了如何将ICCAP测试数据导入ADS进行仿真分析,并导出为通用CSV格式的完整流程。内容涵盖文件格式解析、导入设置、数据验证、处理技巧及常见问题排查,重点解决了数据文件导入过程中的兼容性与单位映射等核心难点,帮助射频工程师高效连接测量与仿真环节。

peace的博客 557

秒懂 Java ExecutorService

是 Java java.util.concurrent 包的重要组成部分,是 Java JDK 提供的框架,用于简化异步模式下任务的执行。一般来说,ExecutorService 会自动提供一个线程池和相关 API,用于为其分配任务。

二师兄撒欢之地 1870

企业碳排放计算方法与实践:从年度总量到月度分配的完整流程

本文系统介绍了企业碳排放计算的全流程方法,包括数据预处理、能源活动与产品生产碳排放计算、年度汇总及月度分配优化。通过ARIMA模型预测补充缺失数据,采用二次规划算法实现基于用电量模式的月度碳排放分配,确保计算结果的准确性与合理性。该方法为企业碳排放管理提供了科学工具,有助于精准监控排放、制定减排策略并满足合规要求。实施中需注重数据质量控制和排放因子选择,并根据企业特点调整参数。该流程适用于制造业企业,为实现碳中和目标提供可靠的数据基础和管理支持。

applehunqiu的博客 1572

Java线程池ExecutorService

目录1 ExecutorService介绍2 ExecutorService的创建3 ExecutorService的使用4 ExecutorService的执行4.1 execute(Runnable)4.2 submit(Runnable)4.3 submit(Callable)4.4 invokeAny(…)4.5 invokeAll(…)5 ExecutorService的关闭6 项目中的使用 1 ExecutorService介绍 本篇主要涉及到的是java.util.concurrent包中的

赵广陆 2万+

AI智能体赋能Cypress:自动化前端测试的新范式

自动化测试是现代软件工程保障质量的核心实践,其原理是通过脚本模拟用户操作,对软件功能进行验证。随着大语言模型(LLM)和智能体(Agent)技术的发展,测试自动化正迈向智能化新阶段。智能体能够理解自然语言描述的测试需求,并自主规划、执行测试步骤,这为应对前端UI频繁变更、测试用例维护成本高等挑战提供了新思路。在工程实践中,将Cypress这一流行的前端测试框架封装为智能体可调用的标准化技能(Skill),是实现这一愿景的关键。通过设计清晰的交互协议和状态管理机制,智能体可以像人类测试工程师一样“感知”页面状

weixin_33726318的博客 686

神经网络基础概念总结(小白入门自用)

神经网络人工神经网络多层感知机激活函数反向传播算法损失函数权值初始化正则化方法 人工神经网络 人工神经元:人工神经元是人工神经网络的基本单元。模拟生物神经元,人工神经元有1个或者多个输入(模拟多个树突或者多个神经元向该神经元传递神经冲动);对输入进行加权求和(模拟细胞体将神经信号进行积累和树突强度不同);对输入之和使用激活函数计算活性值(模拟细胞体产生兴奋或者抑制);输出活性值并传递到下一个人工神经元(模拟生物神经元通过轴突将神经冲动输入到下一个神经元)。 人工神经网络:大量的人工神经元以某种链接方式得来的

qq_42011158的博客 648

java ExecutorService线程池使用(ExecutorService/Completable异步+ExecutorService线程池)

使用自定义配置的线程池,// 核心线程数// 最大线程数// 非核心线程空闲存活时间// 有界队列// 拒绝策略,默认就是拒绝策略// 创建自定义线程池unit,workQueue,handler// 创建自定义线程池(周期性执行)unit,workQueue,handlerCPU 密集型:CPU 核心数 + 1(减少上下文切换)IO 密集型:2 * CPU 核心数(线程常阻塞,需更多线程)根据系统资源设置,避免资源耗尽(如 corePoolSize * 1.5)

abcnull 的博客 1481

CTS实战:如何用set_sense优化时钟树平衡(附ICC2避坑指南)

本文深入探讨了在时钟树综合(CTS)中,如何正确使用`set_sense`命令优化时钟树平衡,并对比了其与`set_disable_timing`的本质区别。通过实战案例详细解析了`-stop_propagation`和`-clock_leaf`参数的应用场景,并提供了ICC2工具中的关键避坑指南,帮助后端工程师精准控制时钟拓扑,避免时序分析漏洞。

weixin_28933797的博客 457

Java 线程池与 ExecutorService 详解

在多线程编程中,线程池是一种非常重要的技术,它可以有效地管理线程的生命周期,减少线程创建和销毁的开销,并提高程序的性能。Java 提供了 `ExecutorService` 接口和 `Executors` 工具类来简化线程池的使用。本文将详细介绍线程池的概念、使用方法以及注意事项。

李长渊的博客 1337

手撕Lua字节码:从黑盒到透明

lua 字节码 怎么‘手撕’一个 chunk 看看里面啥样?我手里有一个.luac或出来的二进制字节码,想知道里面到底是什么结构、哪些字段、有哪些指令,怎么一步一步“拆箱”,从一个黑盒变成有迹可循的东西?也就是:不满足于只会loadpcall而是想亲眼看看一个 chunk 内部长啥样,甚至写点工具把它解析出来。这篇就用带你从“拿到一坨.luac不搞高深玄学,尽量让你看完就能自己动手。注:以 Lua 5.3/5.4 为主,细节各版本略有不同,但大体套路是一致的。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 97

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java线程池ExecutorService学习和使用

线程池中有3个线程 (pool-1-thread-1、pool-1-thread-2 和 pool-1-thread-3),每个线程可以同时执行一个任务。如果需要每个任务执行之后需要返回一个结果,可以实现Callable接口并重写call方法。每个任务执行的过程包括打印任务开始的信息、模拟执行2秒、打印任务完成的信息。每个任务执行2秒,然后完成,接着线程池中的线程会继续执行等待中的任务。前3个任务会立即被分配给线程池中的3个线程并开始执行。使用一个固定大小为3的线程池来并发执行这些任务。

Dd_ddc的博客 3664

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Java ExecutorService管理线程池的简单用法

可以在 java.util.concurrent中找到管理线程池的顶级接口 Executors import java.util.concurrent.*; Executors 接口定义了一个 execute()方法,接收一个实例化的Runnable对象,来启动这个任务,不过常用的还是 ExecutorService 类 ExecutorService 类继承自 Executors,但是提供相当...

AKGWSB 's blog 474

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java线程池ExecutorService中重要的方法

ExecutorService 介绍 ExecutorService是java线程池定义的一个接口,它在java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法。 Java API对ExecutorService接口实现有两个,所以这两个即是线程池的具体实现。 1. ThreadPoolExecutor 2. ScheduledThreadPoolExecutor ExecutorService还继承了Executor接口。 实线表示继承,需要表示实现

Linux,Java,SpringBoot,Python,Lua略知一点 836

java 线程池之ExecutorService

一个执行器,它提供线程池终止的方法,以及可以产生Future来跟踪一个或多个异步任务进度的方法。/*** 启动程序关闭,线程池不会在接收新的任务,但是会将线程池中剩余未执行的任务全部执行完成后,彻底关闭线程池。* 此方法不会等待主动执行的任务终止。使用awaitTermination来完成该操作。*//*** 立马关闭线程池,调用此方法后,线程池中正在执行的任务会尝试中断,未执行的任务会从队列中出栈。返回正在等待执行的任务列表。* 此方法不会等待主动执行的任务终止。

w_hname的博客 645

Java线程池ExecutorService的使用

开篇前,我们先来看看不使用线程池的情况: new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 2 3 4 5 6 7 newThread(newRunnable() { @Override publicvoidrun() { ...

daxiaoge111的博客 337

Java线程池 ExecutorService、ThreadPoolExecutor、ScheduledThreadPoolExecutor及Executors工厂类

Java中的线程池类有两个,分别是:ThreadPoolExecutor和ScheduledThreadPoolExecutor,这两个类都继承自ExecutorService。利用这两个类,可以创建各种不同的Java线程池,为了方便我们创建线程池,Java API提供了Executors工厂类来帮助我们创建各种各样的线程池。下面我们分别介绍一下这三个类。 Java线程池ExecutorService继承树: 1、ExecutorService介绍 ExecutorService是Java中对线.

Janson_Lin 2404

java 关闭线程池_java如何使用ExecutorService关闭线程池?

java如何使用ExecutorService关闭线程池?发布时间:2020-05-23 16:50:46来源:亿速云阅读:355作者:鸽子ExecutorService让我们可以优雅地在程序中使用线程池来创建和管理线程,而且性能佳、开销小,还可以有效地控制最大并发线程数,是我们在java并发编程中会经常使用到的。每一个线程都会占用系统资源,因此线程池的关闭与清理同样重要,本文介绍我们如何优雅地关...

weixin_39655049的博客 884
上一篇: netty(一)
下一篇: java的内部类解析
@@老胡
博客等级 码龄7年 291粉丝 184原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值