面试官:线程池的7种创建方式,你都清楚吗?

文章目录

  • 前言
  • 1. 固定数量的线程池
    • a. 线程池返回结果
    • b. ⾃定义线程池名称或优先级
  • 2. 带缓存的线程池
  • 3. 执⾏定时任务
    • a. 延迟执行(一次)
    • b. 固定频率执行
    • c. scheduleAtFixedRate VS scheduleWithFixedDelay
  • 4. 定时任务单线程
  • 5. 单线程线程池
  • 6. 根据当前CPU⽣成线程池


前言

线程池的创建⽅法总共有 7 种,但总体来说可分为 2 类:

  1. 通过 ThreadPoolExecutor 创建的线程池;
  2. 通过 Executors 创建的线程池。

线程池的创建⽅式总共包含以下 7 种(其中 6 种是通过 Executors 创建的, 1 种是通过ThreadPoolExecutor 创建的):

  1. Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待;
  2. Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
  3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
  4. Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
  5. Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执⾏延迟任务的线程池;
  6. Executors.newWorkStealingPool:创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】。
  7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置,后⾯会详细讲。

1. 固定数量的线程池

public class ThreadPoolDemo3 {public static void main(String[] args) {ExecutorService threadPool = Executors.newFixedThreadPool(2);//添加任务方式 1threadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});//添加任务方式2threadPool.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});}
}
输出:
pool-1-thread-1
pool-1-thread-2

a. 线程池返回结果

public class ThreadPoolDemo4 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService threadPool =  Executors.newFixedThreadPool(2);//执行任务Future<Integer> result = threadPool.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int num = new Random().nextInt(10);System.out.println("随机数" + num);return num;}});//打印线程池返回方式System.out.println("返回结果:" + result.get());}
}
输出
随机数8
返回结果:8

使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。

图片

b. ⾃定义线程池名称或优先级

public class ThreadPoolDemo5 {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建线程工厂ThreadFactory threadFactory = new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {//!!!!!!!一定要注意:要把任务Runnable设置给新创建的线程Thread thread = new Thread(r);//设置线程的命名规则thread.setName("我的线程" + r.hashCode());//设置线程的优先级thread.setPriority(Thread.MAX_PRIORITY);return thread;}};ExecutorService threadPool = Executors.newFixedThreadPool(2,threadFactory);//执行任务1Future<Integer> result = threadPool.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int num = new Random().nextInt(10);System.out.println(Thread.currentThread().getPriority() + ", 随机数:" + num);return num;}});//打印线程池返回结果System.out.println("返回结果:" + result.get());}
}

提供的功能:

  1. 设置(线程池中)线程的命名规则。
  2. 设置线程的优先级。
  3. 设置线程分组。
  4. 设置线程类型(用户线程、守护线程)。

2. 带缓存的线程池

public class ThreadPoolDemo6 {public static void main(String[] args) {//创建线程池ExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {int finalI = i;service.submit(() -> {System.out.println("i : " + finalI + "|线程名称:" + Thread.currentThread().getName());});}}
}
输出
i : 1|线程名称:pool-1-thread-2
i : 4|线程名称:pool-1-thread-5
i : 3|线程名称:pool-1-thread-4
i : 5|线程名称:pool-1-thread-6
i : 0|线程名称:pool-1-thread-1
i : 2|线程名称:pool-1-thread-3
i : 6|线程名称:pool-1-thread-7
i : 7|线程名称:pool-1-thread-8
i : 8|线程名称:pool-1-thread-9
i : 9|线程名称:pool-1-thread-1

优点:线程池会根据任务数量创建线程池,并且在一定时间内可以重复使用这些线程,产生相应的线程池。

缺点:适用于短时间有大量任务的场景,它的缺点是可能会占用很多的资源。

3. 执⾏定时任务

a. 延迟执行(一次)

public class ThreadPoolDemo7 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务的时间:" + LocalDateTime.now());//执行定时任务(延迟3s执行)只执行一次service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行子任务:" + LocalDateTime.now());}},3, TimeUnit.SECONDS);}
}
输出
添加任务的时间:2022-04-13T14:19:39.983
执行子任务:2022-04-13T14:19:42.987

图片

b. 固定频率执行

public class ThreadPoolDemo8 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());}},2,4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:24:38.810
执行任务:2022-04-13T14:24:40.814
执行任务:2022-04-13T14:24:44.814
执行任务:2022-04-13T14:24:48.813
执行任务:2022-04-13T14:24:52.815
执行任务:2022-04-13T14:24:56.813
执行任务:2022-04-13T14:25:00.813
执行任务:2022-04-13T14:25:04.814
执行任务:2022-04-13T14:25:08.813
... ...
... ...
执行任务:2022-04-13T14:26:44.814
执行任务:2022-04-13T14:26:48.813

注意事项:

public class ThreadPoolDemo9 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("执行任务: " + LocalDateTime.now());try {Thread.sleep(5 * 1000);} catch (InterruptedException e) {e.printStackTrace();}}},2,4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:33:34.551
执行任务: 2022-04-13T14:33:36.556
执行任务: 2022-04-13T14:33:41.557
执行任务: 2022-04-13T14:33:46.559
执行任务: 2022-04-13T14:33:51.561
执行任务: 2022-04-13T14:33:56.562
执行任务: 2022-04-13T14:34:01.564
执行任务: 2022-04-13T14:34:06.566
执行任务: 2022-04-13T14:34:11.566
执行任务: 2022-04-13T14:34:16.567
执行任务: 2022-04-13T14:34:21.570
执行任务: 2022-04-13T14:34:26.570
... ....

图片

图片

c. scheduleAtFixedRate VS scheduleWithFixedDelay

scheduleAtFixedRate 是以上⼀次任务的开始时间,作为下次定时任务的参考时间的(参考时间+延迟任务=任务执⾏)。scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的。

public class ThreadPoolDemo10 {public static void main(String[] args) {//创建线程池ScheduledExecutorService service = Executors.newScheduledThreadPool(5);System.out.println("添加任务时间:" + LocalDateTime.now());//2s之后开始执行定时任务,定时任务每隔4s执行一次service.scheduleWithFixedDelay(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + LocalDateTime.now());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, 2, 4, TimeUnit.SECONDS);}
}
输出
添加任务时间:2022-04-13T14:46:02.871
执行任务:2022-04-13T14:46:04.876
执行任务:2022-04-13T14:46:09.878
执行任务:2022-04-13T14:46:14.880
执行任务:2022-04-13T14:46:19.883
执行任务:2022-04-13T14:46:24.885
执行任务:2022-04-13T14:46:29.888
执行任务:2022-04-13T14:46:34.888
执行任务:2022-04-13T14:46:39.891
执行任务:2022-04-13T14:46:44.893
执行任务:2022-04-13T14:46:49.895
执行任务:2022-04-13T14:46:54.897
执行任务:2022-04-13T14:46:59.900
执行任务:2022-04-13T14:47:04.901
... ...

图片

4. 定时任务单线程

public class ThreadPoolDemo11 {public static void main(String[] args) {ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();System.out.println("添加任务的时间:" + LocalDateTime.now());service.schedule(new Runnable() {@Overridepublic void run() {System.out.println("执行时间:" + LocalDateTime.now());}},2, TimeUnit.SECONDS );}
}
输出
添加任务的时间:2022-04-13T15:06:38.100
执行时间:2022-04-13T15:06:40.106

5. 单线程线程池

public class ThreadPoolDemo12 {public static void main(String[] args) {ExecutorService service = Executors.newSingleThreadScheduledExecutor();for (int i = 0; i < 10; i++) {service.submit(new Runnable() {@Overridepublic void run() {System.out.println("线程名:" + Thread.currentThread().getName());}});}}
}
输出
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1

(MS) 为什么不直接用线程?

单线程的线程池又什么意义?

  1. 复用线程。
  2. 单线程的线程池提供了任务队列和拒绝策略(当任务队列满了之后(Integer.MAX_VALUE),新来的任务就会拒绝策略)

6. 根据当前CPU⽣成线程池

public class ThreadPoolDemo13 {public static void main(String[] args) {ExecutorService service = Executors.newWorkStealingPool();for (int i = 0; i < 10; i++) {service.submit(() -> {System.out.println("线程名" + Thread.currentThread().getName());});while(!service.isTerminated()) {}}}
}
输出
线程名ForkJoinPool-1-worker-1

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

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

相关文章

CRM管理系统八大特性,如何帮助企业提升业务效能?

CRM管理系统的使用率逐年上升&#xff0c;这离不开企业对客户的依赖——管理好客户关系是企业发展你的重要因素&#xff0c;由此可见CRM对于任何成长中的企业都是必不可少的。以前我们写过很多关于CRM功能的文章&#xff0c;这篇文章换个思路&#xff0c;想一想CRM管理系统主要…

Pytorch从零开始实战15

Pytorch从零开始实战——ResNeXt-50算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——ResNeXt-50算法实战环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytor…

Unity中Shader序列图动画(UV流动的通用起始点)

文章目录 前言一、一般序列帧动画是按照序列图如下顺序读取的二、在Shader找到UV流动的起始点1、先实现纹理采样2、得到 uv 走格的单位格子大小3、定位到左上角为起始单位格 三、使UV流动的起始点通用化1、在属性面板接收 行 和 列的属性2、看图片可以总结出第一个单元格的公式…

Kotlin/JS工程构建及编译运行到浏览器

概述 Kotlin/JS 提供了转换 Kotlin 代码、Kotlin 标准库的能力&#xff0c;并且兼容 JavaScript 的任何依赖项。Kotlin/JS 的当前实现以 ES5 为目标。 使用 Kotlin/JS 的推荐方法是通过 kotlin.multiplatform Gradle 插件。它提供了一种集中且便捷的方式来设置与控制以 JavaS…

华为DriveONE电机控制器拆解实拍

如果说之前的问界M5、M7&#xff0c;华为让我们看到其在智能化上确实拥有遥遥领先的能力&#xff0c;那么在智界S7上&#xff0c;则让我们看到华为在动力、底盘这些硬件执行层面&#xff0c;竟然也有不输给很多车企的实力。1、华为电驱&#xff0c;全球第一&#xff1f;在智界S…

8K超高清应用:输电线网智慧巡检提升巡视效率

电力安全关系国计民生&#xff0c;是国家安全的重要保障&#xff0c;因此确保电力线路系统的安全运行至关重要。电力线路系统整体分为三大板块&#xff1a;输电线路、变电站和配电线路。然而&#xff0c;由于自然灾害、人为破坏等因素影响&#xff0c;这三大板块的设备很容易发…

开启Hyper-V

开启Hyper-V 为了给windows-ltsc激活&#xff0c;只好给系统装个虚拟机服务器。VMware太大了&#xff0c;于是想起Hyper-V。 走起。 在搜索栏直接搜索“windows功能”就能找到“开启或关闭windows功能”&#xff0c;直接勾选Hyper-V&#xff0c;就能安装了。重启后&#xff0c;…

不同阶数的巴特沃斯低通滤波器的空间域表示——数字图像处理

原理 巴特沃斯低通滤波器&#xff08;Butterworth Low-Pass Filter&#xff09;在频率域中的定义是明确的&#xff0c;但它在空间域中的表示不是直观的。这是因为巴特沃斯滤波器的形式是基于频率的&#xff0c;并且其空间域表示涉及到一个复杂的逆傅里叶变换&#xff0c;该变换…

透明展示柜的安装方法

透明展示柜的安装方法主要包括以下步骤&#xff1a; 准备工具和材料&#xff1a;在安装前&#xff0c;需要准备相应的工具和材料&#xff0c;如螺丝刀、电钻、固定架、玻璃板、胶水等。 确定安装位置&#xff1a;选择一个合适的安装位置&#xff0c;确保展示柜的摆放位置合理&…

关于“Python”的核心知识点整理大全62

目录 20.2.2 安装 Heroku Toolbelt 20.2.3 安装必要的包 注意 20.2.4 创建包含包列表的文件 requirements.txt requirements.txt requirements.txt 注意 20.2.5 指定 Python 版本 runtime.txt 注意 20.2.6 为部署到 Herohu 而修改 settings.py settings.py 20.2.7…

SparkStreaming基础解析(四)

1、 Spark Streaming概述 1.1 Spark Streaming是什么 Spark Streaming用于流式数据的处理。Spark Streaming支持的数据输入源很多&#xff0c;例如&#xff1a;Kafka、Flume、Twitter、ZeroMQ和简单的TCP套接字等等。数据输入后可以用Spark的高度抽象原语如&#xff1a;map、…

鸿蒙南向开发—OpenHarmony技术编译构建框架

概述 OpenHarmony编译子系统是以GN和Ninja构建为基座&#xff0c;对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能扩展的系统&#xff0c;该系统提供以下基本功能&#xff1a; 以部件为最小粒度拼装产品和独立编译。支持轻量、小型、标准三种系…

竞赛保研 基于机器视觉的行人口罩佩戴检测

简介 2020新冠爆发以来&#xff0c;疫情牵动着全国人民的心&#xff0c;一线医护工作者在最前线抗击疫情的同时&#xff0c;我们也可以看到很多科技行业和人工智能领域的从业者&#xff0c;也在贡献着他们的力量。近些天来&#xff0c;旷视、商汤、海康、百度都多家科技公司研…

思科常用图标大全Cisco产品图标库Icon(附PPT下载)

华为企业网络常用图标大全&#xff08;附PPT下载&#xff09;-CSDN博客文章浏览阅读2.8k次。PPT完整版获取交换机&WLAN服务器网络&网管建筑公共终端end_华为企业网络常用图标大全https://blog.csdn.net/XMWS_IT/article/details/120864637?ops_request_misc%257B%2522…

OpenAI ChatGPT-4开发笔记2024-03:Chat之Function Calling/Function/Tool/Tool_Choice

Updates on Function Calling were a major highlight at OpenAI DevDay. In another world,原来的function call都不再正常工作了&#xff0c;必须全部重写。 function和function call全部由tool和tool_choice取代。2023年11月之前关于function call的代码都准备翘翘。 干嘛…

【Java EE初阶八】多线程案例(计时器模型)

1. java标准库的计时器 1.1 关于计时器 计时器类似闹钟&#xff0c;有定时的功能&#xff0c;其主要是到时间就会执行某一操作&#xff0c;即可以指定时间&#xff0c;去执行某一逻辑&#xff08;某一代码&#xff09;。 1.2 计时器的简单介绍 在java标准库中&#xff0c;提供…

新手可理解的PyTorch线性层解析:神经网络的构建基石

目录 torch.nn子模块Linear Layers详解 nn.Identity Identity 类描述 Identity 类的功能和作用 Identity 类的参数 形状 示例代码 nn.Linear Linear 类描述 Linear 类的功能和作用 Linear 类的参数 形状 变量 示例代码 nn.Bilinear Bilinear 类的功能和作用 B…

国家信息安全水平等级考试NISP二级题目卷⑥(包含答案)

国家信息安全水平等级考试NISP二级题目卷&#xff08;六&#xff09; 国家信息安全水平等级考试NISP二级题目卷&#xff08;六&#xff09;需要报考咨询可以私信博主&#xff01; 前言&#xff1a; 国家信息安全水平考试(NISP)二级&#xff0c;被称为校园版”CISP”,由中国信息…

用友U8 Cloud smartweb2.RPC.d XML外部实体注入漏洞

产品介绍 用友U8cloud是用友推出的新一代云ERP&#xff0c;主要聚焦成长型、创新型、集团型企业&#xff0c;提供企业级云ERP整体解决方案。它包含ERP的各项应用&#xff0c;包括iUAP、财务会计、iUFO cloud、供应链与质量管理、人力资源、生产制造、管理会计、资产管理&#…

基于gamma矫正的照片亮度调整(python和opencv实现)

import cv2 import numpy as npdef adjust_gamma(image, gamma1.0):invGamma 1.0 / gammatable np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8")return cv2.LUT(image, table)# 读取图像 original cv2.imread("tes…