【JavaEE】多线程(7) -- 线程池的概念和简单实现

目录

1.线程池是什么

2.标准库中的线程池

2.1ThreadPoolExecutor

 2.2构造方法参数介绍

2.3拒绝策略(面试易考)

 2.4Executor的使用

3.实现线程池


1.线程池是什么

线程池是一种用来管理线程的机制,它可以有效地控制线程的创建、复用和销毁,从而提高程序的性能和资源利用率。

想象这么⼀个场景:

在学校附近新开了⼀家快递店,老板很精明,想到⼀个与众不同的办法来经营。店里没有雇⼈,而是 每次有业务来了,就现场找⼀名同学过来把快递送了,然后解雇同学。这个类⽐我们平时来⼀个任 务,起⼀个线程进行处理的模式。

很快⽼板发现问题来了,每次招聘 + 解雇同学的成本还是非常高的。老板还是很善于变通的,知道 了为什么⼤家都要雇⼈了,所以指定了⼀个指标,公司业务⼈员会扩张到 3 个⼈,但还是随着业务 逐步雇⼈。于是再有业务来了,老板就看,如果现在公司还没 3 个⼈,就雇⼀个⼈去送快递,否则 只是把业务放到⼀个本本上,等着 3 个快递⼈员空闲的时候去处理。这个就是我们要带出的线程池的模式。

 线程池最大的好处就是减少每次启动、销毁线程的损耗。

2.标准库中的线程池

2.1ThreadPoolExecutor

 

2.2构造方法参数介绍

以最后一个构造方法为例:

Java的 ThreadPoolExecutor 是一个线程池执行器,用于管理和调度线程的执行。它有以下几个参数:

1.corePoolSize:核心线程数

        即线程池中保持活动状态的最小线程数。如果线程池中的线程数小于corePoolSize,则即使其他线程是空闲的,ThreadPoolExecutor也会创建新的线程来处理任务。

2.maximumPoolSize:最大线程数

        即线程池中允许的最大线程数。当队列满了且当前线程数小于maximumPoolSize时,ThreadPoolExecutor会创建新的线程来处理任务。

3.keepAliveTime:线程保持活动的时间

        即当线程池中的线程数量大于corePoolSize时,空闲线程被保留的最长时间。超过这个时间,空闲线程将被终止。

4.unit:线程保持活动时间的单位

        可以是纳秒、微秒、毫秒、秒、分钟、小时或天。

5.workQueue:任务队列

        用于保存等待执行的任务。ThreadPoolExecutor提供了多种类型的队列,如ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。

6.threadFactory:线程工厂

        用于创建新线程。可以通过实现ThreadFactory接口来自定义线程的创建过程。

7.handler:拒绝策略

        用于处理无法添加到线程池的任务。拒绝策略可以ThreadPoolExecutor提供的几种默认策略,如AbortPolicy、CallerRunsPolicy、DiscardPolicy和DiscardOldestPolicy,也可以自定义实现RejectedExecutionHandler接口来定义自己的策略。

这些参数可以通过ThreadPoolExecutor的构造方法来设置,也可以通过相应的setter方法进行设置。根据具体的需求,可以调整这些参数来优化线程池的性能和行为。

2.3拒绝策略(面试易考)

在多线程编程中,当线程池无法接受新的任务时,就会触发拒绝策略(RejectedExecutionHandler)。拒绝策略是一个接口,用于定义当线程池无法接受新的任务时应该如何处理这些被拒绝的任务。
在Java中,有四种内置的拒绝策略:

1.AbortPolicy(默认):当线程池无法接受新的任务时,会抛出RejectedExecutionException异常。
2.CallerRunsPolicy:当线程池无法接受新的任务时,会由调用execute方法的线程来执行该任务。
3.DiscardOldestPolicy:当线程池无法接受新的任务时,会抛弃队列中最旧的任务,然后尝试再次提交新的任务。
4.DiscardPolicy:当线程池无法接受新的任务时,会直接抛弃被拒绝的任务。


除了以上四种内置的拒绝策略,我们还可以自定义拒绝策略,只需要实现RejectedExecutionHandler接口,并实现其唯一的方法rejectedExecution(Runnable r, ThreadPoolExecutor executor)。在该方法中,可以根据需求实现自定义的拒绝逻辑,如记录日志、发送通知等。然后,可以通过ThreadPoolExecutor的setRejectedExecutionHandler方法将自定义的拒绝策略设置给线程池。

ThreadPoolExecutor 本身用起来比较复杂, 因此标准库还提供了另一个版本, 把ThreadPoolExecutor封装了一下. 这个版本就是Executors类.

Executors类创建的线程池适用于一些简单的场景,不需要过多的自定义配置。而ThreadPoolExecutor适用于需要更多自定义配置的场景,可以根据需要灵活地配置线程池。

Executors中的方法:

 2.4Executor的使用

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadDemo32 {public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(4);//使用submit添加任务service.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});//ThreadPoolExecutor也是通过submit添加任务, 只是构造方法不同}
}

3.实现线程池

  • 核⼼操作为 submit, 将任务加⼊线程池中
  • 使⽤ Worker 类描述⼀个⼯作线程. 使⽤ Runnable 描述⼀个任务.
  •  使⽤⼀个 BlockingQueue 组织所有的任务
  •  每个 worker 线程要做的事情: 不停的从 BlockingQueue 中取任务并执⾏.
  •  指定⼀下线程池中的最⼤线程数 maxWorkerCount; 当当前线程数超过这个最⼤值时, 就不再新增 线程了.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;class MyThreadPoolExecutor {private final List<Thread> threadList = new ArrayList<>();private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);//n来指定创多少的线程public MyThreadPoolExecutor(int n) {for(int i = 0; i<n; i++) {Thread t = new Thread(()-> {//线程要做的事情是把任务队列中的任务不停的取出来,并且去执行while(true) {try {//此处的take带有阻塞功能, 如果队列为空, 此处就阻塞Runnable runnable = queue.take();//取出一个任务就执行一个任务即可runnable.run();}catch (InterruptedException e) {e.printStackTrace();}}});t.start();threadList.add(t);}}public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}
}

使用示例:

public class ThreadDemo33 {public static void main(String[] args) throws InterruptedException {MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);for (int i = 0; i < 1000; i++) {int n = i;executor.submit(new Runnable() {@Overridepublic void run() {System.out.println("执行任务" + n + ", 当前线程为:" + Thread.currentThread().getName());}});}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/586020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序的编译、链接

目录 前言&#xff1a; 前置知识回顾 宏 宏定义常量 宏定义语句 宏定义函数 条件编译 应用场景 编译过程概览 预编译阶段 编译阶段 汇编阶段 链接阶段 前言&#xff1a; 在ANSI C的任何一种实现中&#xff0c;存在两种不同的环境&#xff0c;第1种是翻译环境&#x…

EE Vocabulary(电气工程词汇库)

前言 整理了一些EE&#xff08;电子工程&#xff09;和CS&#xff08;计算机&#xff09;专业的学生们阅读英文文献或写论文常用的一些词汇。 仓库GitHub地址&#xff1a;https://github.com/Phillweston/EE_Vocabulary 内容 仓库包含以下格式的电气工程词汇&#xff1a; …

GPT-5、开源、更强的ChatGPT!OpenAI公布2024年计划

年终岁尾&#xff0c;正值圣诞节热闹气氛的OpenAI写下了2024年的发展清单。 OpenAI联合创始人兼首席执行官Sam Altman在社交平台公布&#xff0c;AGI&#xff08;稍晚一些&#xff09;、GPT-5、更好的语音模型、更高的费率限制&#xff1b; 更好的GPTs&#xff1b;更好的推理…

代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II、 55. 跳跃游戏、45.跳跃游戏II

122.买卖股票的最佳时机II 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;贪心算法也能解决股票问题&#xff01;LeetCode&#xff1a;122.买卖股票最佳时机II_哔哩哔哩_bi…

大数据- Hadoop入门

目录 &#x1f436;2.1 hadoop的简介 1. 概述 2. 什么是分布式&#xff1f; 3. Hadoop的指代 &#x1f436;2.2 hadoop的发展历程 &#x1f436;2.3 hadoop的版本介绍 &#x1f436;2.4 hadoop的常用端口号 &#x1f436;2.5 hadoop的设计目的 &#x1f436;2.6 hadoo…

Java集合/泛型篇----第二篇

系列文章目录 文章目录 系列文章目录前言一、说说List,Set,Map三者的区别二、Array与ArrayList有什么不一样?三、Map有什么特点四、集合类存放于 Java.util 包中, 主要有几 种接口前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。…

upload-labs Pass-03(黑名单验证,特殊后缀)问题纠正

php任何后缀名解析 背景&#xff1a;为了验证php解析不依靠后缀名&#xff0c;可以是任何后缀名&#xff0c;纠正upload-labs Pass-03&#xff08;黑名单验证&#xff0c;特殊后缀&#xff09;里所说的几个固定的后缀名理论是错误的。1 部署1.1 环境准备1.1.1 系统、内核&#…

【音视频 ffmpeg 学习】 跑示例程序 持续更新中

环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…

计算机毕业设计-----ssm流浪狗领养系统

项目介绍 我国的动物管理正处于起步阶段&#xff0c;注册在线的宠物数量非常有限&#xff0c;信息也很封闭&#xff0c;因此必须发挥民间力量扩容&#xff0c;加强宠物信息的宣传力度&#xff0c;使更多爱护动物的好心人可以领养宠物&#xff0c;同时也就收纳有家宠物信息&…

Efficient Classification of Very Large Images with Tiny Objects(CVPR2022补1)

文章目录 Two-stage Hierarchical Attention SamplingOne-stageTwo-Stage内存需求 Efficient Contrastive Learning with Attention Sampling Two-stage Hierarchical Attention Sampling 一阶段缩放是hw&#xff0c;提取的特征是h1w1&#xff0c; 二阶段缩放是uv&#xff08;…

Mongodb聚合操作中的$type

在mongodb查询语句中&#xff0c;用户可以通过指定$type值&#xff0c;查询出的符合字段类型的文档数据。在mongodb聚合操作中&#xff0c;也存在$type操作符。本文就聚合操作中的$type进行介绍。 定义 返回一个表示传入参数BSON类型的字符串。在聚合操作中&#xff0c;按照下…

leetcode贪心(最大子序列和、分发饼干、摆动序列)

455.分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有…

iPortal内置Elasticsearch启动失败的几种情况——Linux

作者&#xff1a;yx 文章目录 前言一、端口占用二、ES启动过慢三、磁盘占用过高&#xff0c;导致ES变为只读模式 前言 在Linux环境启动iPortal后有时会出现搜索异常的情况&#xff0c;如下截图&#xff0c;这是因为Elasticsearch&#xff08;以下简称“ES”&#xff09;没启动…

快速理解ASCII、GBK、Unicode、UTF-8、ANSI

文章大部分内容来源于非官方说明&#xff0c;且无法用逻辑推理出结果&#xff0c;准确性仅供参考。 ASCII 计算机是老外发明的&#xff0c;想让计算机实现更多的功能&#xff0c;必然少不了把常用的字母和符号存进去&#xff0c;甚至包含一些特殊符号&#xff0c;于是ASCII码…

剑指 Offer(第2版)面试题 60:n 个骰子的点数

剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1a;n 个骰子的点数 剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1a;n 个骰子的点数解法 1&#xff1a;递归解法 2&#xff1a;动态规划 剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1…

共享单车之数据可视化

文章目录 第1关&#xff1a;绘制地图第2关&#xff1a;绘制流量最高的五条线路的路程图 第1关&#xff1a;绘制地图 任务描述 本关任务&#xff1a;使用JSP在百度地图上绘制一条共享单车起始路程。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何创建地…

进阶学习——Linux系统服务器硬件认识与RAID磁盘

目录 一、服务器知识补充 1.硬件 2.服务器常见故障 二、认识RAID 1.什么是RAID 2.RAID的优点 3.RAID的实现方式 三、RAID磁盘陈列 1.RAID 0 磁盘陈列介绍——RAID 0 2.RAID 1 磁盘陈列介绍——RAID 1 3.RAID 5 磁盘陈列介绍——RAID 5 4.RAID 6 磁盘陈列介绍——RA…

vr体验馆用什么软件计时计费,如遇到停电软件程序如何恢复时间

vr体验馆用什么软件计时计费&#xff0c;如遇到停电软件程序如何恢复时间 一、软件程序问答 如下图&#xff0c;软件以 佳易王vr体验馆计时计费软件V17.9为例说明 1、软件如何计时间&#xff1f; 点击相应编号的开始计时按钮即可 2、遇到停电再打开软件时间可以恢复吗&…

【开源】基于Vue+SpringBoot的公司货物订单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 客户管理模块2.2 商品维护模块2.3 供应商管理模块2.4 订单管理模块 三、系统展示四、核心代码4.1 查询供应商信息4.2 新增商品信息4.3 查询客户信息4.4 新增订单信息4.5 添加跟进子订单 五、免责说明 一、摘要 1.1 项目…

Redis经典五大类型源码及底层实现(一)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…