线程池-打开方式

应用程序进程(二):启动线程池 各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。BAT大厂面试题、独家面试工具包,资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取。 阅读详情

为什么不推荐使用Executors

底层确实是通过LinkedBlockingQueue实现的,默认不设置队列大小的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致OOM,报错如下:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
   at java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:416)
   at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
   at com.hollis.ExecutorsDemo.main(ExecutorsDemo.java:16)

创建线程池的正确姿势

public class ExecutorsDemo {
   private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
       .setNameFormat("demo-pool-%d").build();

   private static ExecutorService pool = new ThreadPoolExecutor(5, 200,
       0L, TimeUnit.MILLISECONDS,
       new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

   public static void main(String[] args) {
       for (int i = 0; i < Integer.MAX_VALUE; i++) {
           pool.execute(new SubThread());
       }
   }
}

关闭线程池

long start = System.currentTimeMillis();
for (int i = 0; i <= 5; i++) {
    pool.execute(new Job());
}
    pool.shutdown();
    while (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
           LOGGER.info("线程还在执行。。。");
}
    long end = System.currentTimeMillis();
    LOGGER.info("一共处理了【{}】", (end - start));

SpringBoot 使用线程池

//线程池配置
@Configuration
public class TreadPoolConfig {
    /**
     * 消费队列线程
     * @return
     */
    @Bean(value = "consumerQueueThreadPool")
    public ExecutorService buildConsumerQueueThreadPool(){
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("consumer-queue-thread-%d").build();

        ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(5),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy());

        return pool ;
    }
}
//线程池使用
@Resource(name = "consumerQueueThreadPool")
    private ExecutorService consumerQueueThreadPool;
    @Override
    public void execute() {
        //消费队列
        for (int i = 0; i < 5; i++) {
            consumerQueueThreadPool.execute(new ConsumerQueueThread());
        }
    }

线程池隔离
hystrix 隔离
首先需要定义两个线程池,分别用于执行订单、处理用户。

/**
 * Function:订单服务
 *
 * @author crossoverJie
 *         Date: 2018/7/28 16:43
 * @since JDK 1.8
 */
public class CommandOrder extends HystrixCommand<String> {

    private final static Logger LOGGER = LoggerFactory.getLogger(CommandOrder.class);

    private String orderName;

    public CommandOrder(String orderName) {


        super(Setter.withGroupKey(
                //服务分组
                HystrixCommandGroupKey.Factory.asKey("OrderGroup"))
                //线程分组
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("OrderPool"))

                //线程池配置
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                        .withCoreSize(10)
                        .withKeepAliveTimeMinutes(5)
                        .withMaxQueueSize(10)
                        .withQueueSizeRejectionThreshold(10000))

                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
        )
        ;
        this.orderName = orderName;
    }


    @Override
    public String run() throws Exception {

        LOGGER.info("orderName=[{}]", orderName);

        TimeUnit.MILLISECONDS.sleep(100);
        return "OrderName=" + orderName;
    }


}


/**
 * Function:用户服务
 *
 * @author crossoverJie
 *         Date: 2018/7/28 16:43
 * @since JDK 1.8
 */
public class CommandUser extends HystrixCommand<String> {

    private final static Logger LOGGER = LoggerFactory.getLogger(CommandUser.class);

    private String userName;

    public CommandUser(String userName) {


        super(Setter.withGroupKey(
                //服务分组
                HystrixCommandGroupKey.Factory.asKey("UserGroup"))
                //线程分组
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("UserPool"))

                //线程池配置
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                        .withCoreSize(10)
                        .withKeepAliveTimeMinutes(5)
                        .withMaxQueueSize(10)
                        .withQueueSizeRejectionThreshold(10000))

                //线程池隔离
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
        )
        ;
        this.userName = userName;
    }


    @Override
    public String run() throws Exception {

        LOGGER.info("userName=[{}]", userName);

        TimeUnit.MILLISECONDS.sleep(100);
        return "userName=" + userName;
    }
}

模拟运行:

public static void main(String[] args) throws Exception {
        CommandOrder commandPhone = new CommandOrder("手机");
        CommandOrder command = new CommandOrder("电视");

        //阻塞方式执行
        String execute = commandPhone.execute();
        LOGGER.info("execute=[{}]", execute);

        //异步非阻塞方式
        Future<String> queue = command.queue();
        String value = queue.get(200, TimeUnit.MILLISECONDS);
        LOGGER.info("value=[{}]", value);

        CommandUser commandUser = new CommandUser("张三");
        String name = commandUser.execute();
        LOGGER.info("name=[{}]", name);
    }

原理:利用一个 Map 来存放不同业务对应的线程池。
注意:自定义的 Command 并不是一个单例,每次执行需要 new 一个实例,不然会报 This instance can only be executed once. Please instantiate a new instance.

喜欢的小伙伴可以点点赞,小编在学习过程中整理了一些学习资料,可以分享给做java的工程师朋友们,相互学习,需要的可以关注公众号 l谈java 即可免费获取Java架构学习资料和面试专题及答案!

Qt Concurrent实战避坑指南:从QObject继承到线程池的正确打开方式 本文深入探讨了Qt Concurrent模块在多线程编程中的实战应用与避坑指南,重点解析了从QObject继承到线程池的正确使用方式。通过实际案例揭示了QtConcurrent::run()调用成员函数时的常见陷阱,并提供了线程安全、生命周期管理、性能优化等关键解决方案,帮助开发者高效利用Qt并发模块提升应用性能。 阅读详情

相关推荐

Sentaurus TCAD学习——Scheme编程语言

sentaurus scheme语言学习记录

摸摸小熊猫的博客 964

C#线程开启的四种方式

线程控制

风,停了 1524

C++实战指南:使用CodeBlocks构建跨平台wxWidgets窗口应用

本文是一份面向C++初学者的实战指南,详细介绍了如何使用CodeBlocks IDE和wxWidgets框架快速构建跨平台的桌面窗口应用。内容涵盖从环境搭建、项目配置到界面设计、事件处理的全流程,重点讲解了如何利用CodeBlocks的开箱即用支持和wxSmith可视化设计器,高效开发具有按钮、菜单、列表等控件的交互式窗口界面程序,帮助读者轻松入门GUI开发。

weixin_29012677的博客 154

java开启线程的几种方法

这个之后在看。

qq_52122048的博客 1272

从Delta Delay到Timing Window:详解数字芯片后端时序差异的那些坑

本文深入剖析了数字芯片后端设计中,模块级与系统级时序分析结果不一致的核心原因。重点解释了Delta Delay如何导致模块级分析的乐观假设,以及Timing Window(时序窗口)差异如何通过影响串扰噪声计算,在顶层集成时引发新的时序违例,尤其是保持时间问题。文章为工程师提供了从约束建模到签核策略的系统性应对方案。

beer8的博客 499

2025.05.30【转录组】|Ribo-seq数据流程详解(一 质量控制)

本文详细介绍了Ribo-seq数据的质控分析流程,重点讲解了使用fastp进行原始数据质控的关键步骤和参数设置。作者通过Snakemake自动化流程示例,展示了如何去除接头序列、过滤低质量reads、生成质控报告等操作。文章强调高质量的Ribo-seq数据对转录后调控和翻译动态研究的重要性,并提供了兼顾数据质量和下游分析需求的参数配置建议。该流程有助于研究人员规范高效地完成Ribo-seq数据质控,为后续分析提供可靠数据基础。

785

线程池方式开启线程--submit()和execute()的区别

没有引用线程池的时候,需要我们通过继承Thread类和实现Runnable、Callable接口,最终调用start()方法启动线程。现在我们可以通过线程池的execute()和submit()方法来提交线程任务。

m0_57640408的博客 2353

【Agent从入门到实践】01 从“工具函数”到“智能体”:Agent与传统程序的核心区别

传统程序是“你教它怎么做,它才做什么”,Agent是“你告诉它做什么,它自己想怎么做”。从技术层面来说,这个区别的背后,是Agent融合了大语言模型(LLM)、记忆能力、工具调用能力、决策能力等技术,才实现了“自主思考”和“灵活执行”,而这些技术,咱们会在后面的章节中一步步拆解,手把手教大家实现。

人工智能AI技术 988

JAVA 线程池的正确打开方式

JAVA 线程池的正确打开方式 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 当前环境 jdk == 1.8 Executors 使用的隐患 先来看一段代码,我们要创建一个固定线程池,假设固定线程数是4。代码如下: Executors是JAVA并发包中提供的,用来...

weixin_33862514的博客 628

108、AWB 时间滤波器:帧间白平衡平滑,防止色彩跳变与过冲

摘要: 文章探讨了AWB(自动白平衡)时间滤波器的设计与优化,以解决帧间白平衡跳变和过冲问题。通过自适应状态机(STABLE/TRANSITION/JUMP)动态调整平滑系数alpha,结合帧率归一化和过冲保护(方向检测+限幅),实现场景切换快速响应与静态稳定性的平衡。作者分享了工程经验:避免固定阈值、联动AE/AF、真实场景验证,并推荐简化卡尔曼滤波替代IIR。最终方案在旗舰机前置摄像头中成功消除“闪白”现象,强调参数需动态适应光照与色温变化。

sundong_81的博客 64

OpenClaw 子代理配对失败问题分析与解决方案

OpenClaw子代理配对失败问题分析与解决方案 问题核心在于agent设备权限不足,仅有operator.approvals权限而缺少operator.admin权限,导致子代理启动时形成权限死锁。本文提供三种解决方案: 直接编辑设备配对文件(推荐):修改本地JSON文件,为agent设备添加完整operator.admin权限,操作简单快捷。 标准重新配对流程:删除现有agent设备后重新配对,通过正常审批流程获取完整权限,符合系统安全设计。 修改源码降低权限要求(仅限开发环境):调整子代理代码避免强制

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 149

线程池的正确打开方式

欢迎关注微信公众号:程序员小圈圈原文首发于:www.zhangruibin.com 本文出自于:RebornChang的博客 转载请标明出处^_^ 线程池的正确打开方式 线程,线程池,多线程,锁,老生常谈的知识点了,涉及很多知识,本节为笔者自己整理的知识点,方便学习记忆,分享出来仅供参考。 线程相关 线程与进程 线程是什么,进程是什么,这是很多初学者的疑问,当然老鸟大神请忽略,这里就简单的比...

Reborn_Chang的博客 661

PX4从放弃到精通(十九):串口驱动

文章目录前言一、创建进程二、编写驱动 前言 硬件: PIXHAWK4 USB转串口模块 软件: Ubuntu18.04 PX4 1.11.3固件 QGC地面站 串口助手 一、创建进程 参考:https://mbot1.blog.youkuaiyun.com/article/details/122587617 二、编写驱动 .........

超维空间科技的博客 4598

多线程——线程池的正确打开方式

线程可认为是操作系统可调度的最小的程序执行序列,一般作为进程的组成部分,同一进程中多个线程可共享该进程的资源(如内存等)。JVM线程跟内核轻量级进程有一对一的映射关系,所以JVM中的线程是很宝贵的。一般在工程上多线程的实现是基于线程池的。因为相比自己创建线程,多线程具有以下优点。

2401_83384536的博客 1038

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java线程池的正确打开方式

当前环境jdk == 1.8Executors 使用的隐患先来看一段代码,我们要创建一个固定线程池,假设固定线程数是4。代码如下:Executors是JAVA并发包中提供的,用来快速创建不同类型的线程池。是不是很简单,创建线程池只需一行代码。对于一些个人项目或临时性的项目,这样写确实没什么问题,而且开发速度很快。但在一些大型项目中,这种做法一般是禁止的。WHY???因为用Executors创建的线...

大道至简 7042

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

多线程--线程池的正确打开方式

概述传奇小说网 https://www.xs86.com 线程可认为是操作系统可调度的最小的程序执行序列,一般作为进程的组成部分,同一进程中多个线程可共享该进程的资源(如内存等)。JVM线程跟内核轻量级进程有一对一的映射关系,所以JVM中的线程是很宝贵的。 一般在工程上多线程的实现是基于线程池的。因为相比自己创建线程,多线程具有以下优点 线程是稀缺资源,使用线程池可以减少创建和销毁线程的...

终极冥帝 146

WINCC7.3破解文件

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

【多线程】线程池的正确打开方式

目录 一,Executors与ThreadPoolExecutor 二,使用ThreadPoolExecutor创建线程池 创建线程池 解读 三,我们来看看JAVA的Executors提供的工厂方法。 newSingleThreadExecutor newFixedThreadPool newCachedThreadPool newScheduledThreadPool 说明:Executors 各个方法的弊端: newFixedThreadPool 和 newSingleT...

lixianghai2010的专栏 343

JAVA线程池的正确打开方式

当前环境 jdk == 1.8 Executors 使用的隐患 先来看一段代码,我们要创建一个固定线程池,假设固定线程数是4。代码如下: Executors是JAVA并发包中提供的,用来快速创建不同类型的线程池。 是不是很简单,创建线程池只需一行代码。对于一些个人项目或临时性的项目,这样写确实没什么问题,而且开发速度很快。但在一些大型项目中,这种做法一般是禁止的。 WHY??? 因为用Execu...

Ccccyxji的博客 369

JAVA 线程池的正确打开方式(转)

前环境 jdk == 1.8 Executors 使用的隐患 先来看一段代码,我们要创建一个固定线程池,假设固定线程数是4。代码如下: Executors是JAVA并发包中提供的,用来快速创建不同类型的线程池。 是不是很简单,创建线程池只需一行代码。对于一些个人项目或临时性的项目,这样写确实没什么问题,而且开发速度很快。但在一些大型项目中,这种做法一般是禁止的。 WHY???...

frank1998819 174

线程池创建的正确方式

https://blog.youkuaiyun.com/hollis_chuang/article/details/83743723

zhaoyang10的专栏 422
上一篇: 程序猿面试十家,只斩获两家
下一篇: 谈谈JVM-深堆、浅堆
Formor_
博客等级 码龄7年 7粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值