Java 线程池 参数

news2024/11/26 2:56:20

1、为什么要使用线程池

线程池能有效管控线程,统一分配任务,优化资源使用。

2、线程池的参数

创建线程池,在构造一个新的线程池时,必须满足下面的条件:

corePoolSize(线程池基本大小)必须大于或等于0;
maximumPoolSize(线程池最大大小)必须大于或等于1;
maximumPoolSize必须大于或等于corePoolSize;
keepAliveTime(线程存活保持时间)必须大于或等于0;
workQueue(任务队列)不能为空;
threadFactory(线程工厂)不能为空,默认为DefaultThreadFactory类(可以通过线程工厂对不同线程池的线程名称进行设置,以区分产生bug的线程是哪个池的)
handler(线程饱和策略)不能为空,默认策略为ThreadPoolExecutor.AbortPolicy。

线程池参数围绕两个核心,线程任务

线程相关的参数:核心线程数,最大线程数,线程存活保持时间,线程饱和策略,线程工厂。

任务相关的参数:任务队列。

3、线程池执行过程

1、创建核心线程处理任务,失败则继续

2、将任务添加到任务队列

3、创建非核心线程处理任务

4、线程饱和策略

4、核心参数分析

4.1 任务队列

4.1.1 直接提交队列SynchronousQueue

设置为SynchronousQueue队列,SynchronousQueue是一个特殊的BlockingQueue,它没有容量,每执行一个插入操作就会阻塞。一般使用SynchronousQueue都会要求为无界(maximumPoolSize=Integer.MAX_VALUE)。

public class PoolTask implements Runnable{
    public int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 正在执行 " + i + " 号任务");
    }

    public PoolTask(int i) {
        this.i = i;
    }
}
    public static void main(String[] args) {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new SynchronousQueue<>());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            threadPoolExecutor.execute(poolTask);
        }
        threadPoolExecutor.shutdown();

    }

执行结果:


4.1.2 有界的任务队列ArrayBlockingQueue

一般使用ArrayBlockingQueue来实现。使用ArrayBlockingQueue有界任务队列,若有新的任务需要执行时,线程池会创建新的线程,直到创建的线程数量达到corePoolSize时,会将新的任务加入到等待队列中。这里等待队列的任务数量设置为2,若等待队列已满,即超过ArrayBlockingQueue初始化的容量,则继续创建线程,直到线程数量达到maximumPoolSize设置的最大线程数量,若大于maximumPoolSize,则执行拒绝策略。

    public static void main(String[] args) {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2));
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            threadPoolExecutor.execute(poolTask);
        }
        threadPoolExecutor.shutdown();
    }

执行结果:

4.1.3 无界的任务队列LinkedBlockingQueue

一般使用LinkedBlockingQueue来实现。使用无界的任务队列,线程池的任务队列可以无限制添加新任务,而线程池创建的最大线程数就是corePoolSize设置的数量,这种情况下maximumPoolSize设置的值是不会生效的,就算等待队列中有许多未执行的任务,线程池的数量达到了corePoolSize的值后也不会增加新的线程。

    public static void main(String[] args) {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            threadPoolExecutor.execute(poolTask);
        }
        threadPoolExecutor.shutdown();
    }

运行结果:


4.1.4 优先任务队列PriorityBlockingQueue

一般使用PriorityBlockingQueue来实现。任务需要实现comparable接口,根据任务的优先级执行任务。

public class PoolTask implements Runnable, Comparable<PoolTask>{
    public int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 正在执行 " + i + " 号任务");
    }

    public PoolTask(int i) {
        this.i = i;
    }

    @Override
    public int compareTo(PoolTask o) {
        //升序排序
        return o.getI() - this.getI();
    }
}
    public static void main(String[] args) {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            threadPoolExecutor.execute(poolTask);
        }
        threadPoolExecutor.shutdown();
    }

运行结果:

4.2 线程饱和策略

4.2.1 ThreadPoolExecutor.AbortPolicy

线程池默认的阻塞策略。不执行此任务,而且抛出一个运行时异常(未检查的异常RejectedExecutionException)。

切记:ThreadPoolExecutor.execute需要try catch,否则程序会直接退出。

ThreadPoolExecutor.DiscardPolicy

不执行此任务,而且不抛异常。(是个空方法)

public class PoolTask implements Runnable, Comparable<PoolTask>{
    public int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 正在执行 " + i + " 号任务");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public PoolTask(int i) {
        this.i = i;
    }

    @Override
    public int compareTo(PoolTask o) {
        //升序排序
        return o.getI() - this.getI();
    }
}
public class PoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            try {
                threadPoolExecutor.execute(poolTask);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        threadPoolExecutor.shutdown();
    }
}

运行结果:

4.2.2 ThreadPoolExecutor.DiscardOldestPolicy

从队列里删除最老的任务(头部的一个任务),并再次execute 此task。

public class PoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            try {
                threadPoolExecutor.execute(poolTask);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        threadPoolExecutor.shutdown();
    }
}

运行结果:

4.2.3 ThreadPoolExecutor.CallerRunsPolicy

让调用execute方法的线程执行此command,会阻塞入口。

这是个调节机制,既不抛弃任务也不抛出异常,而是将某些任务回退到调用者,让调用者所在的线程去执行。

public class PoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            try {
                threadPoolExecutor.execute(poolTask);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        threadPoolExecutor.shutdown();
    }
}

运行结果:

4.2.4 用户自定义拒绝策略(最常用)

实现RejectedExecutionHandler,并自己定义策略模式

package com.example.dyc.mythreadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

public class MyThreadPolicy implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (r instanceof PoolTask){
            PoolTask poolTask = (PoolTask) r;
            if (poolTask.getI() != 6){
                return;
            }
            System.out.println("获取到六号任务,试图放入队列");
            BlockingQueue<Runnable> queue = executor.getQueue();
            while (true) {
                if (queue.remainingCapacity() > 0) {
                    queue.add(poolTask);
                    System.out.println("放入队列成功");
                    break;
                } else {
                    try {
                        System.out.println("放入队列失败,继续试图放入");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }
}
public class PoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 5000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new MyThreadPolicy());
        for (int i = 0; i < 10; i++) {
            PoolTask poolTask = new PoolTask(i);
            try {
                threadPoolExecutor.execute(poolTask);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        threadPoolExecutor.shutdown();
    }
}

运行结果:

5 常用线程池类型

java通过Executors提供四种线程池,分别为:

5.1 newCachedThreadPool


newCachedThreadPool创建一个可缓存的无界线程池,如果线程池长度超过处理需要,可灵活回收空线程,若无可回收,则新建线程。当线程池中的线程空闲时间超过60s,则会自动回收该线程,当任务超过线程池的线程数则创建新的线程,线程池的大小上限为Integer.MAX_VALUE,可看作无限大。


5.2 newFixedThreadPool


newFixedThreadPool创建一个指定大小的线程池,可控制线程的最大并发数,超出的线程会在LinkedBlockingQueue阻塞队列中等待。


5.3 newScheduledThreadPool

newScheduledThreadPool线程池支持定时以及周期性执行任务,创建一个corePoolSize为传入参数,最大线程数为整形的最大数的线程池



5.4 newSingleThreadExecutor


newSingleThreadExecutor创建一个单线程化的线程池,它只有一个线程,用仅有的一个线程来执行任务,保证所有的任务按照指定顺序(FIFO,LIFO,优先级)执行,所有的任务都保存在队列LinkedBlockingQueue中,等待唯一的单线程来执行任务。

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

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

相关文章

JVM流程图自我总结

JVM流程图总览 运行时数据区是否有GC、OOM图 从线程共享角度区别图

【深度学习】最强算法之:图神经网络(GNN)

图神经网络 1、引言2、图神经网络2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.4.1 GNN2.4.2 GCN 2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;给俺讲一讲图神经网络啊 小鱼&#xff1a;你看&#xff0c;我这会在忙着呢 小屌丝&#xff1a;啊~ 小鱼&#…

如何在Rust中操作JSON

❝ 越努力&#xff0c;越幸运 ❞ 大家好&#xff0c;我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。 前言 我们之前在Rust 赋能前端-开发一款属于你的前端脚手架中有过在Rust项目中如何操作JSON。 由于文章篇幅的原因&#xff0c;我们就没详细介绍…

java算法day48 | 动态规划part09 ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III

198.打家劫舍 class Solution {public int rob(int[] nums) {if(nums.length0) return 0;if(nums.length1) return nums[0];int[] dpnew int[nums.length];dp[0]nums[0];dp[1]Math.max(nums[1],nums[0]);for(int i2;i<nums.length;i){dp[i]Math.max(dp[i-1],dp[i-2]nums[i])…

网络工程师笔记18(关于网络的一些基本知识)

网络的分类 介绍计算机网络的基本概念&#xff0c;这一章最主要的内容是计算机网络的体系结构-ISO 开放系统互连参考模型&#xff0c;其中的基本概念&#xff0c;例如协议实体、协议数据单元&#xff0c;服务数据单元、面向连接的服务和无连接的服务、服务原语、服务访问点、相…

ubuntu 安装 mysql8,远程连接数据库(华为云、压缩包安装、问题解决)

下载解压 mysql8 cd /usr/local/ wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz tar -Jvxf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz修改 mysql 文件夹名&#xff0c;设置环境变量 mv mysql-8.0.33-linux-glibc2…

javaScript中原型链

一、原型链 js 的对象分为普通对象和函数对象。每个对象都有__proto__ 但是只有函数对象 (非箭头函数) 才有 prototype 属性。 new的过程&#xff1a; 1、创建一个空的简单 javaScript对象 2、将空对象的 __proto__连接到该函数的 prototype 3、将函数的this指向新创建的对象…

【教程】iOS Swift应用加固

&#x1f512; 保护您的iOS应用免受恶意攻击&#xff01;在本篇博客中&#xff0c;我们将介绍如何使用HTTPCORE DES加密来加固您的应用程序&#xff0c;并优化其安全性。通过以下步骤&#xff0c;您可以确保您的应用在运行过程中不会遭受数据泄露和未授权访问的风险。 摘要 …

抖音视频评论关键词采集工具|评论ID提取下载软件

抖音评论关键词采集工具&#xff1a;批量拓客&#xff0c;轻松抓取 最新版本的抖音评论关键词采集工具带来了许多实用功能&#xff0c;帮助您更便捷地抓取抖音视频评论。通过输入关键词和评论监控词&#xff0c;您可以快速建立抓取任务并获取相关数据。以下是该工具的主要功能&…

STM32存储左右互搏 SDIO总线读写SD/MicroSD/TF卡

STM32存储左右互搏 SDIO总线读写SD/MicroSD/TF卡 SD/MicroSD/TF卡是基于FLASH的一种常见非易失存储单元&#xff0c;由接口协议电路和FLASH构成。市面上由不同尺寸和不同容量的卡&#xff0c;手机领域用的TF卡实际就是MicroSD卡&#xff0c;尺寸比SD卡小&#xff0c;而电路和协…

在线免费图像处理

功能 尺寸修改(自定义和内置常用的照片尺寸)图像压缩(比较好的情况最高可以压缩 10 倍, 如果是无损压缩可以压缩 5 倍左右,参数范围 50~70 左右)图像方向修改图像格式修改修改后的效果支持实时反馈, 并且支持点击图像预览,同时保留历史修改图片(在预览中可以查看)支持修改撤回…

【Spring】一问详解什么是Spring IoC和DI

目录 一、IoC & DI入门1.1、Spring1.1.1、什么是容器1.1.2、什么是IoC 1.2、IoC介绍1.2.1、传统程序开发1.2.2、问题分析1.2.3、问题解决1.2.4、 IoC优势 1.3、Bean的作用域1.4、DI介绍 二、IoC详解2.1、Bean的存储2.1.1、类注解的使用2.1.2、获取bean对象的其他方式2.1.3、…

k8s_入门_命令详解

命令详解 kubectl是官方的CLI命令行工具&#xff0c;用于与 apiserver进行通信&#xff0c;将用户在命令行输入的命令&#xff0c;组织并转化为 apiserver能识别的信息&#xff0c;进而实现管理k8s各种资源的一种有效途径 1. 帮助 2. 查看版本信息 3. 查看资源对象等 查看No…

小型企业网络安全指南

许多小型企业刚刚起步&#xff0c;没有大公司所拥有的相同资源来保护其数据。他们不仅可能没有资金来支持多样化的安全计划&#xff0c;而且也可能没有人力或时间。 网络犯罪分子知道小型企业缺乏这些资源&#xff0c;并利用这些资源来谋取利益。遭受网络攻击后&#xff0c;小…

c语言:操作符

操作符 一.算术操作符: + - * % / 1.除了%操作符之外,其他的几个操作符可以作用与整数和浮点数,如:5%2.0//error. 2.对于操作符,如果两个操作数都为整数,执行整数除法而只要有浮点数执行的就是浮点数除法。 3.%操作符的两个操作数必须为整数。 二.移位操作符:<&…

Windows(Win11) 安装 Docker (Docker Desktop)

目录 前言 下载 安装 wsl 安装 Docker Desktop 启动 Docker Desktop 配置国内镜像 拉取镜像 前言 一般 docker 都是直接安装在 Linux 服务器上&#xff0c;用来快速部署一些中间件&#xff08;比如 redis&#xff0c;rocketmq等等&#xff09;&#xff0c;省去繁琐的安…

Qt QML的插件(Qt Quick 2 Extension Plugin)方法

Qt Quick的插件方法 序言环境前置注意概念——Qt Quick插件的相关知识插件里的qml文件模块名的相关知识模块名本身注意事项模块名版本注意事项 以示例来说明创建插件qmltypes的生成qmltypes的可能性失效 插件的编码注意1、插件模块版本控制2、pro里的注意 调用插件插件信息输入…

element-ui drawer 组件源码分享

今日简单分享 drawer 组件的源码实现&#xff0c;从以下五个方面来分享&#xff1a; 1、drawer 组件页面结构 2、drawer 组件属性 3、drawer 组件 slot 4、drawer 组件方法 5、drawer 组件事件 一、drawer 组件页面结构 二、drawer 组件属性 2.1 append-to-body 属性&am…

(Atcoder Beginner Contest 348)题解

前言 这是我第 4 4 4 次做出 F F F 题&#xff0c;庆祝上蓝&#xff01; 正题 本题解提供 A − F A-F A−F 题题解&#xff0c;欢迎诸位大佬参考。 第 1 题 Penalty Kick 照例很水&#xff0c;模拟即可。 #include <bits/stdc.h> using namespace std; #define…

一种新兴的身份安全理念:身份结构免疫

文章目录 前言一、从身份管理到身份结构免疫二、身份结构免疫应用实践三、典型应用场景前言 随着组织的数字身份数量激增,基于身份的网络攻击活动也在不断增长。在身份优先的安全原则下,新一代身份安全方案需要更好的统一性和控制度。而在现有的身份管理模式中,组成业务运营…