线程池(详细)

news2024/11/15 13:28:43

Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用 线程池,必须对其实现原理了如指掌。

在这里插入图片描述

在ThreadPoolExecutor中,当提交一个新任务时,处理流程如下:

如果线程池中的线程数小于核心线程数(corePoolSize),则即使线程池中的其他线程是空闲的,也会创建一个新的线程来处理新提交的任务。
如果线程池中的线程数已经达到核心线程数,新提交的任务会被添加到工作队列中,等待被执行。
如果工作队列已满,并且当前线程数小于最大线程数(maximumPoolSize),则会创建新的非核心线程来处理任务。
如果工作队列已满,并且线程数已经达到最大线程数,这时会触发拒绝策略(RejectedExecutionHandler),根据具体的拒绝策略来处理这个无法被执行的任务。

注意:
空闲线程存活的数量通常不包括核心线程。在ThreadPoolExecutor中,corePoolSize(核心线程数)表示线程池的基本大小,即使在没有任务需要执行时,线程池也会保持这么多线程。这些核心线程在默认情况下即使长时间没有任务执行,也不会被销毁。
而keepAliveTime和maximumPoolSize参数主要用于非核心线程。当线程池中的线程数量超过corePoolSize时,如果某个线程的空闲时间超过了keepAliveTime,那么这个线程就会被终止。因此,keepAliveTime实际上是非核心线程的空闲存活时间。

线程池的使用

线程池的创建

我们可以通过ThreadPoolExecutor来创建一个线程池。
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,milliseconds,runnableTaskQueue, handler);
创建一个线程池时需要输入几个参数,如下。

1)corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。
2)runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。可以选择以下几个阻塞队列。 有界队列和无界队列的区别,使用有界队列的话,当队列饱和并超过最大线程数会执行拒绝策略,无界的话设置maximumPooIsize无意义

  • ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原 则对元素进行排序。
  • LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
  • PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
    3)maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并 且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如 果使用了无界的任务队列这个参数就没什么效果。
    4)ThreadFactory(可选):用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线 程设置有意义的名字,代码如下。
    new ThreadFactoryBuilder().setNameFormat(“XX-task-%d”).build();
    5)RejectedExecutionHandler(饱和策略,可选):当队列和线程池都满了,说明线程池处于饱和状 态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法 处理新任务时抛出异常。在JDK1.5中Java线程池框架提供了以下4种策略。
    ·AbortPolicy:直接抛出异常。
    ·CallerRunsPolicy:只用调用者所在线程来运行任务。
    ·DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
    ·DiscardPolicy:不处理,丢弃掉。
    当然,也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录 日志或持久化存储不能处理的任务。
    6)keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以,如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率。
    7)TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS)、小时(HOURS)、分钟
    (MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒
    (NANOSECONDS,千分之一微秒)。

向线程池提交任务
可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。

  • execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。

通过以下代码可知execute()方法输入的任务是一个Runnable类的实例。
threadsPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
submit()方法用于提交需要返回值的任务。
线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方
法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
Future future = executor.submit(harReturnValuetask);
try {
Object s = future.get();
} catch (InterruptedException e) {
// 处理中断异常
} catch (ExecutionException e) {
// 处理无法执行任务异常
} finally {
// 关闭线程池
executor.shutdown();
}

案例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CustomThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(
                5, // 核心线程数
                10, // 最大线程数
                60, // 空闲线程的存活时间
                TimeUnit.SECONDS,
                new java.util.concurrent.ArrayBlockingQueue<>(9) ,// 任务队列
                new ThreadPoolExecutor.AbortPolicy()//采用默认的拒绝,抛出异常
        );

        // 提交多个下载任务
        for (int i = 0; i < 25; i++) {
            String url = "http://example.com/page" + i;
            executorService.submit(new DownloadTask(url));
        }

        executorService.shutdown(); // 关闭线程池,不再接受新任务,但会等待队列中的任务执行完毕

    }
}
import java.util.concurrent.TimeUnit;

public  class DownloadTask implements Runnable {
    private final String url;
    public DownloadTask(String url) {
        this.url = url;
    }
    @Override
    public void run() {
        try {
            // 模拟下载时间
            long downloadTime = (long) (Math.random() * 2000);
            TimeUnit.MILLISECONDS.sleep(downloadTime);
            System.out.println("Downloaded content from " + url + " in " + downloadTime + "ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

请添加图片描述

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

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

相关文章

2024年电工杯数学建模竞赛思路资料汇总贴

下文包含&#xff1a;2024电工杯&#xff08;电工杯数学建模竞赛&#xff09;思路解析、电工杯参赛时间及规则信息说明、好用的数模技巧及如何备战数学建模竞赛 C君将会第一时间发布选题建议、所有题目的思路解析、相关代码、参考文献、参考论文等多项资料&#xff0c;帮助大家…

前端怎么使用svg格式的图片

目录 第一步&#xff0c;找到图标 第二步&#xff0c;使用 第一种&#xff0c;SVG下载 第二种&#xff0c;粘贴SVG代码 第一步&#xff0c;找到图标 以阿里巴巴矢量图标库为例&#xff0c;随便找一个图标&#xff0c;如下图 第二步&#xff0c;使用 第一种&#xff0c;SV…

Matlab 2023b学习笔记1——界面认识

下载安装好Matlab后&#xff0c;可以看到如下界面&#xff1a; 可以看到&#xff0c;这时只有命令行窗口。我们在上方工具栏中选择“布局”—— “默认”&#xff0c;即可看到左右两边多出来了“当前文件夹”与“工作区”两栏。 一、当前文件夹界面 这个界面显示的是当前目录下…

什么是独特摆动交易策略?fpmarkets1分钟讲清楚

摆动交易策略想必各位投资者都已经接触过了&#xff0c;但是什么是独特摆动交易策略&#xff1f;各位投资者知道吗&#xff1f;其实很简单&#xff0c;这是一种基于斐波纳契工具的独特摆动交易策略。下面fpmarkets1分钟讲清楚&#xff0c;趋势总会经历调整&#xff0c;而这些调…

一个Python浏览器自动化操作神器:Mechanize库

今天&#xff0c;我们将介绍一个强大的Python库——Mechanize&#xff0c;通过它&#xff0c;我们可以轻松实现网页浏览的自动化。 Mechanize是一个用于模拟浏览器行为的Python库。它允许你自动化地与网站进行交互&#xff0c;就像真实用户一样。你可以使用它填写表单、点击按…

Python考试复习--day3

1.统计字符串个数 ninput() z0 s0 k0 o0 for i in n:if i.isalpha():zz1elif i.isnumeric():ss1elif i.isspace():k1else:o1 print(字母有{}个,数字有{}个,空格有{}个,其他字符{}个.format(z,s,k,o))2.分类统计字符 ninput() x0 d0 s0 k0 o0 for i in n:if i.islower():x1elif …

ENVI5.6详细安装教程,亲测可用(附安装包和破解文件)

文件准备 下载链接如下&#xff0c;包括安装包envi5.6.exe和破解需要的文件Crack 链接&#xff1a;https://pan.baidu.com/s/1fLE6VcEOqWpN7h0j99evSw?pwd77zx 提取码&#xff1a;77zx --来自百度网盘超级会员V4的分享开始安装 选择下载好的文件进行解压&#xff0c;鼠标…

17 - grace数据处理 - 补充 - 地下水储量计算过程分解 -- 陆地水储量变化

17 - grace数据处理 - 补充 - 地下水储量计算过程分解 -- 陆地水储量变化 0 引言1 Grace陆地水储量过程整合0 引言 最近关于GRACE地下水储量计算的有关过程多被问起,接下来几篇将介绍关于地下水储量计算的有关内容。由水量平衡方程可以将地下水储量的计算过程分解为4个部分,第…

数据集003:猫类识别-12种猫分类数据集 (含数据集下载链接)

数据集简介&#xff1a; 训练集共有2160张猫的图片, 分为12类. train_list.txt是其标注文件 测试集共有240张猫的图片. 不含标注信息. 训练集图像&#xff08;部分&#xff09; 验证集图像&#xff08;部分&#xff09; 标签 部分代码&#xff1a; # 定义训练数据集 class T…

Devexpress中GridControl控件中的表格遍历逻辑问题

当我们在执行其他事件时&#xff0c;常常需要对GridControl控件里的表内容进行一个遍历逻辑判断&#xff0c;该文以确认2列中的值是否为空为例&#xff1b;首先在遍历模块当然是使用foreach作为遍历的基础&#xff0c;在这其中在此例中存在具体业务细节&#xff0c;需要对选中行…

设置 border 边框单侧样式 - HarmonyOSNext

设置 border 边框单侧样式,通过 api 中查看 border(value: BorderOptions): T; BorderOptions 又包含了若干个子属性 1.width?: EdgeWidths | Length; 2.color?: EdgeColors | ResourceColor; 3.radius?: BorderRadiuses | Length; 4.style?: EdgeStyles | BorderStyle; 其…

OrangePi Kunpeng Pro开发板初体验——家庭小型服务器

引言 在开源硬件的浪潮中&#xff0c;开发板作为创新的基石&#xff0c;正吸引着全球开发者的目光。它们不仅为技术爱好者提供了实验的平台&#xff0c;更为专业开发者带来了实现复杂项目的可能性。本文将深入剖析OrangePi Kunpeng Pro开发板&#xff0c;从开箱到实际应用&…

2024年【G2电站锅炉司炉】免费试题及G2电站锅炉司炉复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【G2电站锅炉司炉】免费试题及G2电站锅炉司炉复审考试&#xff0c;包含G2电站锅炉司炉免费试题答案和解析及G2电站锅炉司炉复审考试练习。安全生产模拟考试一点通结合国家G2电站锅炉司炉考试最新大纲及G2电站锅…

蓝桥杯第十四届国赛B组刷题笔记

A-0子2023&#xff1a; 题目&#xff1a; 小蓝在黑板上连续写下从 11 到 20232023 之间所有的整数&#xff0c;得到了一个数字序列&#xff1a; &#x1d446;12345678910111213...20222023S12345678910111213...20222023。 小蓝想知道 &#x1d446;S 中有多少种子序列恰好等…

豆包模型最新数据评测!性能究竟如何?

豆包模型最新数据评测&#xff01;性能究竟如何&#xff1f; 前言 就在5月27日&#xff0c;字节跳动旗下的豆包大模型在火山引擎原动力大会上正式发布&#xff0c;本次大会中豆包的模型能力也引发行业关注。 介绍豆包 豆包是一个多功能 AI 助手&#xff0c;为你的生活、学习、工…

免费 OSS 资源 Backblaze B2 使用最新指南

免费的对象存储资源日渐枯竭&#xff0c;Backblaze 是为数不多仍提供免费 OSS 的良心厂商。另外一个则是大名鼎鼎的 Cloudflare R2。虽然免费&#xff0c;但 Backblaze 也修改了政策&#xff1a;如果不验证信用卡的话是不能打开 Public 选项的&#xff0c;或者支付一美金。估计…

爬山算法教程(个人总结版)

背景与简介 爬山算法&#xff08;Hill Climbing Algorithm&#xff09;是一种用于解决优化问题的启发式搜索方法。它是一种局部搜索算法&#xff0c;通过不断尝试从当前解出发&#xff0c;在其邻域内寻找更优的解&#xff0c;直到无法找到更优解为止。该算法得名于其类似于登山…

青蛙跳台阶问题

本期介绍&#x1f356; 主要介绍&#xff1a;青蛙跳台阶问题&#xff0c;青蛙跳台阶与斐波那契数列的关系&#x1f440;。 文章目录 1. 题目2. 递归解题思路3. 迭代解题思路 1. 题目 从前有一只青蛙他想跳台阶&#xff0c;有n级台阶&#xff0c;青蛙一次可以跳1级台阶&#xff…

MYSQL之安装

一&#xff0c;下载仓库包 wget -i -c https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm二&#xff0c;安装仓库 yum -y install mysql80-community-release-el7-3.noarch.rpmsed -i s/gpgcheck1/gpgcheck0/g mysql-community.repo三&#xff0c;安装MY…

Python代码:十七、生成列表

1、题目 描述&#xff1a; 一串连续的数据用什么记录最合适&#xff0c;牛牛认为在Python中非列表&#xff08;list&#xff09;莫属了。现输入牛牛朋友们的名字&#xff0c;请使用list函数与split函数将它们封装成列表&#xff0c;再整个输出列表。 输入描述&#xff1a; …