面试笔记——线程池

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

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;综合考虑…

智能合约语言(eDSL)—— wasmtime实现合约引擎补充

1、链上下文 由于我们是应用到区块链中&#xff0c;所以我们需要把链的环境传递给wasmtime&#xff0c;这样wasmtime在运行合约的时候&#xff0c;就可以获取到链上数据&#xff1b;我们运行合约当时的环境&#xff0c;打包成一个变量context&#xff0c;传递给wasmtime。conte…

【如何使用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 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现 一、简单介绍 二、简单…

Visual Studio Installer 运行python 汉字

问题描述&#xff1a; Visual Studio Installer 在正常情况下运行python文件时时候&#xff0c; 不能编译中文注释&#xff0c;更不能输出中文。 解决方法&#xff1a; 在程序开头下面这一行即可。 #coding:GBK 原因及解释&#xff1a; #coding:GBK 是 Python 源文件中的一个…

ceph 1 pool(s) do not have an application enabled

查看 ceph 状态 cluster:id: 58f90b9a-155c-43cf-98af-54cb611fc8e0health: HEALTH_OKservices:mon: 3 daemons, quorum a,b,d (age 79m)ne>mgr: b(active, since 59m), standbys: ane>mds: 1/1 daemons up, 1 hot standbyne>osd: 6 osds: 6 up (since 79m), 6 in…

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

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

Python基本数据类型

描述 Python是一种高级编程语言&#xff0c;拥有丰富的数据类型用于表示不同类型的数据。基本数据类型可以分为数值型&#xff08;Numbers&#xff09;、字符串型&#xff08;Strings&#xff09;、布尔型&#xff08;Booleans&#xff09;、空值&#xff08;NoneType&#xff…

8、Flink 在 source 处生成水位线 和 在 source 之后生成水位线案例

1、AtSourceGenerateWatermark 注意&#xff1a;从 Flink 1.17开始&#xff0c;FLIP-27 源框架支持拆分级别的水印对齐。 import java.time.Duration;public class _02_AtSourceGenerateWatermark {public static void main(String[] args) throws Exception {StreamExecution…

摇杆控制电机

参考&#xff1a; 摇杆电位器控制步进电机正反转调速-Arduino中文社区 - Powered by Discuz! 一个基于树莓派和Python的无人机视觉跟踪系统_ 北漠苍狼的专栏(QQ:1746430162)-CSDN博客

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

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

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

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

【Spring】2.Spring中Bean的生命周期管理及定义

在Spring框架中&#xff0c;Bean是一个被Spring IoC容器实例化、组装和管理的对象。Bean就是Spring应用中的对象&#xff0c;它们形成了Spring应用的骨干。Spring IoC容器负责创建Bean&#xff0c;配置Bean以及管理Bean的完整生命周期。 Bean的生命周期 实例化Bean&#xff1a…

神经网络高效训练:优化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;认识企业设备…