面试笔记——线程池

线程池的核心参数(原理)

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
  • corePoolSize 核心线程数目
  • maximumPoolSize 最大线程数目 = (核心线程+救急线程的最大数目)
  • keepAliveTime 生存时间 : 救急线程的生存时间,生存时间内没有新任务,此线程资源会释放
  • unit 时间单位 :救急线程的生存时间单位,如秒、毫秒等
  • workQueue :当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务
  • threadFactory 线程工厂 :可以定制线程对象的创建,例如设置线程名字、是否是守护线程等
  • handler 拒绝策略:当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略

在这里插入图片描述
使用Demo:

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;public class ThreadPoolDemo implements Runnable {public static void main(String[] args) {//创建阻塞队列LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(100);ArrayBlockingQueue<Runnable> arrayBlockingQueue = new ArrayBlockingQueue<>(5);//创建工厂ThreadFactory threadFactory = new ThreadFactory() {AtomicInteger atomicInteger = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {//创建线程把任务传递进去Thread thread = new Thread(r);//设置线程名称thread.setName("MyThread: "+atomicInteger.getAndIncrement());return thread;}};ThreadPoolExecutor pool  = new ThreadPoolExecutor(2,5,1,TimeUnit.SECONDS,arrayBlockingQueue,threadFactory,new ThreadPoolExecutor.DiscardOldestPolicy());for (int i = 0; i < 100; i++) {pool.submit(new ThreadPoolDemo());}pool.shutdown();}@Overridepublic void run() {//执行业务System.out.println(Thread.currentThread().getName()+" 进来了");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"出去了");}
}

线程池中常见的阻塞队列

workQueue:当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务。

  1. ArrayBlockingQueue:基于数组结构的有界阻塞队列,FIFO。
  2. LinkedBlockingQueue:基于链表结构的有界阻塞队列,FIFO。
  3. DelayedWorkQueue :是一个优先级队列,它可以保证每次出队的任务都是当前队列中执行时间最靠前的
  4. SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作。

ArrayBlockingQueue的LinkedBlockingQueue区别:在这里插入图片描述

确定核心线程数

  • IO密集型任务:核心线程数大小设置为2N+1(N为当前CPU的核数)
    • 一般来说:文件读写、DB读写、网络请求等
  • CPU密集型任务:核心线程数大小设置为N+1
    • 一般来说:计算型代码、Bitmap转换、Gson转换等

查看机器的CPU核数:

public static void main(String[] args) {//查看机器的CPU核数System.out.println(Runtime.getRuntime().availableProcessors());
}

参考回答:

  • 高并发、任务执行时间短 :( CPU核数+1 ),减少线程上下文的切换
  • 并发不高、任务执行时间长
    • IO密集型的任务 : (CPU核数 * 2 + 1)
    • 计算密集型任务 :( CPU核数+1 )
  • 并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考上一条

线程池的种类

在java.util.concurrent.Executors类中提供了大量创建连接池的静态方法,以下四种比较常见。
1. 创建使用固定线程数的线程池 ——适用于任务量已知,相对耗时的任务

public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}

核心线程数与最大线程数一样,没有救急线程
阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE
举例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class FixedThreadPoolCase {static class FixedThreadDemo implements Runnable{@Overridepublic void run() {String name = Thread.currentThread().getName();for (int i = 0; i < 2; i++) {System.out.println(name + ":" + i);}}}public static void main(String[] args) throws InterruptedException {//创建一个固定大小的线程池,核心线程数和最大线程数都是3ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 5; i++) {executorService.submit(new FixedThreadDemo());Thread.sleep(10);}executorService.shutdown();}}

运行结果:

pool-1-thread-1:0
pool-1-thread-1:1
pool-1-thread-2:0
pool-1-thread-2:1
pool-1-thread-3:0
pool-1-thread-3:1
pool-1-thread-1:0
pool-1-thread-1:1
pool-1-thread-2:0
pool-1-thread-2:1

2. 单线程化的线程池,它只会用唯一的工作线程来执行任 务,保证所有任务按照指定顺序(FIFO)执行——适用于按照顺序执行的任务

public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}

核心线程数和最大线程数都是1
阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE

举例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class NewSingleThreadCase {static int count = 0;static class Demo implements Runnable {@Overridepublic void run() {count++;System.out.println(Thread.currentThread().getName() + ":" + count);}}public static void main(String[] args) throws InterruptedException {//单个线程池,核心线程数和最大线程数都是1ExecutorService exec = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {exec.execute(new Demo());Thread.sleep(5);}exec.shutdown();}}

运行结果:

pool-1-thread-1:1
pool-1-thread-1:2
pool-1-thread-1:3
pool-1-thread-1:4
pool-1-thread-1:5
pool-1-thread-1:6
pool-1-thread-1:7
pool-1-thread-1:8
pool-1-thread-1:9
pool-1-thread-1:10

3. 可缓存线程池——适合任务数比较密集,但每个任务执行时间较短的情况

public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}

核心线程数为0
最大线程数是Integer.MAX_VALUE
阻塞队列为SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作。

举例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CachedThreadPoolCase {static class Demo implements Runnable {@Overridepublic void run() {String name = Thread.currentThread().getName();try {//修改睡眠时间,模拟线程执行需要花费的时间Thread.sleep(100);System.out.println(name + "执行完了");} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) throws InterruptedException {//创建一个缓存的线程,没有核心线程数,最大线程数为Integer.MAX_VALUEExecutorService exec = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {exec.execute(new Demo());Thread.sleep(1);}exec.shutdown();}}

运行结果:

pool-1-thread-1执行完了
pool-1-thread-2执行完了
pool-1-thread-3执行完了
pool-1-thread-4执行完了
pool-1-thread-5执行完了
pool-1-thread-6执行完了
pool-1-thread-7执行完了
pool-1-thread-8执行完了
pool-1-thread-9执行完了
pool-1-thread-10执行完了

4. 提供了“延迟”和“周期执行”功能的ThreadPoolExecutor。

public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());
}
public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), handler);
}
public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler);
}

举例

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolCase {static class Task implements Runnable {@Overridepublic void run() {try {String name = Thread.currentThread().getName();System.out.println(name + ", 开始:" + new Date());Thread.sleep(1000);System.out.println(name + ", 结束:" + new Date());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) throws InterruptedException {//按照周期执行的线程池,核心线程数为2,最大线程数为Integer.MAX_VALUEScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);System.out.println("程序开始:" + new Date());/*** schedule 提交任务到线程池中* 第一个参数:提交的任务* 第二个参数:任务执行的延迟时间* 第三个参数:时间单位*/scheduledThreadPool.schedule(new Task(), 0, TimeUnit.SECONDS);scheduledThreadPool.schedule(new Task(), 1, TimeUnit.SECONDS);scheduledThreadPool.schedule(new Task(), 5, TimeUnit.SECONDS);Thread.sleep(5000);// 关闭线程池scheduledThreadPool.shutdown();}}

运行结果:

程序开始:Mon Apr 29 22:26:18 CST 2024
pool-1-thread-1, 开始:Mon Apr 29 22:26:18 CST 2024
pool-1-thread-2, 开始:Mon Apr 29 22:26:19 CST 2024
pool-1-thread-1, 结束:Mon Apr 29 22:26:19 CST 2024
pool-1-thread-2, 结束:Mon Apr 29 22:26:20 CST 2024
pool-1-thread-1, 开始:Mon Apr 29 22:26:23 CST 2024
pool-1-thread-1, 结束:Mon Apr 29 22:26:24 CST 2024

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

为什么不使用Excutors创建线程池

参考阿里开发手册《Java开发手册-嵩山版》
在这里插入图片描述
ps:OOM是指内存溢出。
最后,建议根据计算机的条件使用ThreadPoolExecutor创建线程池(突然感觉上一节白学了,唉~)。

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

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

相关文章

利用word2vec包将中文转变为词向量

代码展示&#xff1a; import jieba import re import json import logging import sys import gensim.models as word2vec from gensim.models.word2vec import LineSentence, loggerpattern u[\\s\\d,.<>/?:;\\"[\\]{}()\\|~!\t"#$%^&*\\-_a-zA-Z&…

C#创建obj三维模型文件

介绍 使用开源库创建obj三维模型文件。 开源库地址&#xff1a;https://github.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj 相关API地址&#xff1a;https://jeremyansel.github.io/JeremyAnsel.Media.WavefrontObj/api/JeremyAnsel.Media.WavefrontObj.ObjFile.html …

【docker】开放Docker端口

【docker 】 安装docker&#xff08;centOS7&#xff09;-CSDN博客 【docker】常用命令-CSDN博客 【docker】centos7配置docker镜像加速_docker仓库加速地址-CSDN博客 【docker】Hello World-CSDN博客 【docker 】Compose 使用介绍_docker compose 使用-CSDN博客 【docker…

linux(ubuntu18.04.2) Qt编译 MySQL(8.0以上版本)链接库 Qt版本 5.12.12及以上 包含Mysql动态库缺失问题

整理这篇文档的意义在于&#xff1a;自己走了很多弯路&#xff0c;淋过雨所以想为别人撑伞&#xff0c;也方便回顾&#xff0c;仅供参考 一、搭建开发环境&#xff1a; 虚拟机&#xff08;ubuntu-20.04.6-desktop-amd64&#xff09;&#xff1a;Mysql数据库 8.0.36Workbench …

tidb离线本地安装及mysql迁移到tidb

一、背景&#xff08;tidb8.0社区版&#xff09; 信创背景下不多说好吧&#xff0c;从资料上查tidb和OceanBase“兼容”&#xff08;这个词有意思&#xff09;的比较好。 其实对比了很多数据库&#xff0c;有些是提供云服务的&#xff0c;有些“不像”mysql&#xff0c;综合考虑…

【如何使用SSH密钥验证提升服务器安全性及操作效率】(优雅的连接到自己的linux服务器)

文章目录 一、理论基础&#xff08;不喜欢这部分的可直接看具体操作&#xff09;1.为什么要看本文&#xff08;为了zhuangbility&#xff09;2.为什么要用密钥验证&#xff08;更安全不易被攻破&#xff09;3.密码验证与密钥验证的区别 二、具体操作1.生成密钥对1.1抉择&#x…

计算机复试项目:SpringCloud实战高并发微服务架构设计

秒杀购物商城--环境搭建 秒杀购物商城基础服务组件--详细介绍 秒杀购物商城基础服务--权限中心 秒杀购物商城业务服务--收货地址 秒杀购物商城业务服务--秒杀活动服务 秒杀购物商城--购物车的功能设计及分析 秒杀购物商城基础服务-用户中心 秒杀购物商城业务服务--商品中…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现 一、简单介绍 二、简单…

ArcGIS小技巧—模型构建器快速提取河网

上篇文章介绍的基于DEM的河网提取&#xff0c;需要使用多个工具&#xff0c;整体操作比较繁琐&#xff0c;在日常工作中&#xff0c;使用Arcgis提供的模型构建器可以帮助我们将多个工具整合在一起&#xff0c;在面对大量数据批量处理时&#xff0c;可以大大提高工作效率 利用模…

数字化wms仓库管理软件,实现企业仓储信息共享与智慧运行-亿发

在经济飞速发展的今天&#xff0c;企业面临着客户需求多样化、质量和交期要求提高以及激烈的市场竞争等挑战。在这样的背景下&#xff0c;许多企业开始考虑采用数字化仓储WMS系统来解决这些问题。 数字化仓储WMS系统通过打造高效、规范的仓库管理体系&#xff0c;实现了对产品…

爱普生晶振在物联网LoRa通讯中的应用

LoRa 是LPWAN通信技术中的一种&#xff0c;是美国Semtech公司采用和推广的一种基于扩频技术的超远距离无线传输方案。这一方案改变了以往关于传输距离与功耗的折衷考虑方式&#xff0c;为用户提供一种简单的能实现远距离、长电池寿命、大容量的系统&#xff0c;进而扩展传感网络…

神经网络高效训练:优化GPU受限环境下的大规模CSV数据处理指南

最近训练模型,需要加载wifi sci data 数据量特别大,直接干爆内存,训练也特别慢,快放弃了!随后冷静下来,然后靠着多年的经验,来进行层层优化,随诞生了这篇博客。 背景介绍 机器学习模型的训练通常需要大量的数据,尤其是对于深度神经网络模型。然而,当数据集非常庞大时…

网络之路29:三层链路聚合

正文共&#xff1a;1666 字 17 图&#xff0c;预估阅读时间&#xff1a;3 分钟 目录 网络之路第一章&#xff1a;Windows系统中的网络 0、序言 1、Windows系统中的网络1.1、桌面中的网卡1.2、命令行中的网卡1.3、路由表1.4、家用路由器 网络之路第二章&#xff1a;认识企业设备…

新质生产力实践,我用chatgpt开发网站

是的&#xff0c;我用chatgpt开发了一个网站&#xff0c;很轻松。 我之前一点不懂前端&#xff0c;也没有网站开发的代码基础&#xff0c;纯正的0基础。 从0开始到最后成品上线&#xff0c;时间总计起来大致一共花了2-3周的时间。 初始想法我是想给我公司开发一个网站&#…

【弱监督语义分割】AllSpark:从transformer中的未标记特征重生标记特征,用于半监督语义分割

AllSpark: Reborn Labeled Features from Unlabeled in Transformer for Semi-Supervised Semantic Segmentation 摘要&#xff1a; 目前最先进的方法是用真实标签训练标注数据&#xff0c;用伪标签训练未标注数据。然而&#xff0c;这两个训练流程是分开的&#xff0c;这就使…

Android数据恢复:如何在手机上恢复丢失的文件和照片

我们都有 我们错误地从手机中删除重要内容的时刻。确实如此 不一定是我们的错。其他人可以对您的手机数据执行此操作 有意或无意。这在某个时间点发生在我们所有人身上。 但是&#xff0c;今天市场上有各种各样的软件可以 帮助恢复已删除的文件。这些类型的软件被归类为数据恢复…

Pandas数据可视化 - Matplotlib、Seaborn、Pandas Plot、Plotly

可视化工具介绍 让我们一起探讨Matplotlib、Seaborn、Pandas Plot和Plotly这四个数据可视化库的优缺点以及各自的适用场景。这有助于你根据不同的需求选择合适的工具。 1. Matplotlib 优点: 功能强大&#xff1a;几乎可以用于绘制任何静态、动画和交互式图表。高度可定制&a…

用OpenCV先去除边框线,以提升OCR准确率

在OpenCV的魔力下&#xff0c;我们如魔法师般巧妙地抹去表格的边框线&#xff0c;让文字如诗如画地跃然纸上。 首先&#xff0c;我们挥动魔杖&#xff0c;将五彩斑斓的图像转化为单一的灰度世界&#xff0c;如同将一幅绚丽的油画化为水墨画&#xff0c;通过cv2.cvtColor()函数的…

寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)

贵工程寝室快修目录 目录 基于SprinBootvue的贵工程寝室快修小程序 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 在线报修管理 3公告信息管理 4论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&a…

结构方程模型【SEM】:非线性、非正态、交互作用及分类变量分析

张老师&#xff08;研究员&#xff09;&#xff0c;长期从事R语言结构方程模型、群落生态学、保护生物学、景观生态学和生态模型方面的研究和教学工作&#xff0c;已发表了多篇论文&#xff0c;拥有丰富的科研及实践经验。 利用结构方程模型建模往往遇到很多‘特殊’情况&…