百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

Java 线程池规范使用示例(java线程池入门)

yund56 2025-07-08 23:23 4 浏览

1 摘要

Java 线程池在批量处理的场景中应用广泛。常见的四种创建线程池的方法:newSingleThreadExecutor,newFixedThreadPool,newCachedThreadPool,newScheduledThreadPool,各有各的缺陷,不建议使用。本文将给出根据阿里巴巴Java开发手册推荐的方式创建线程池的示例。

2 推荐创建线程池的方法

java.util.concurrent.ThreadPoolExecutor

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

参数说明:

corePoolSize: 线程池核心线程数量,推荐为服务器的核心数量

maximumPoolSize: 线程池最大线程数量,推荐为和服务核心数量的两倍

keepAliveTime: 线程销毁等待时间,当线程数超过核心线程数量(corePoolSize)时,销毁多余线程需要等待的最大时间;可根据任务执行的频率设置时间长度

unit: 线程销毁等待时间单位,有毫秒,秒,小时等

workQueue: 工作负载阻塞队列,当线程池中线程数量达到最大值时,仍然有未处理的任务,此时会将任务放在该队列中

threadFactory: 线程工厂,用于创建线程

RejectedExecutionHandler: 线程池拒绝策略,当线程数量达到线程池最大值,工作负载队列满了之后,线程池对于新任务的处理策略。有四种:


java.util.concurrent.ThreadPoolExecutor.AbortPolicy: 抛出异常,不作处理


java.util.concurrent.ThreadPoolExecutor.DiscardPolicy: 丢弃新任务,也不抛出异常


java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy: 丢弃最老的任务


java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy: 把任务交给调用线程池的线程处理,直到线程池死了


通常情况下选择抛出异常的策略即可。

3 核心示例代码

3.1 任务负载

./src/main/java/com/ljq/demo/concurrent/DrinkTask.java

1

package com.ljq.demo.concurrent;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;

/**

* @Description: 喝酒任务

* @Author: junqiang.lu

* @Date: 2021/5/14

*/

@Slf4j

public class DrinkTask implements Callable<Integer> {

/**

* 当前杯数

*/

private int cupNumber;

public DrinkTask(int cupNumber) {

this.cupNumber = cupNumber;

}

@Override

public Integer call() throws Exception {

log.info("武松喝完了第[" + cupNumber + "]杯酒");

Thread.sleep(100);

return cupNumber;

}

}

3.2 简易线程池工具类

./src/main/java/com/ljq/demo/util/ThreadPoolUtil.java

1

package com.ljq.demo.util;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**

* @Description: 线程池工具类

* @Author: junqiang.lu

* @Date: 2021/5/14

*/

public class ThreadPoolUtil {

private ThreadPoolUtil(){

}

static {

initExecutor();

}

/**

* 线程池执行器

*/

private static transient ThreadPoolExecutor executor;

/**

* 执行任务

* (不包含返回值)

*

* @param command

*/

public static void execute(Runnable command) {

executor.execute(command);

}

/**

* 执行任务

* (包含返回值)

*

* @param task

* @param <T>

* @return

*/

public static <T> Future<T> executeAsync(Callable<T> task) {

return executor.submit(task);

}

/**

* 销毁线程池

*/

public static void shutdown() {

executor.shutdown();

}

/**

* 初始化线程池

*/

private static void initExecutor() {

if (executor == null || executor.isShutdown()) {

synchronized (ThreadPoolUtil.class) {

if (executor == null || executor.isShutdown()) {

executor = new ThreadPoolExecutor(4,10,100,

TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1000),

ThreadFactoryBuilder.create().build(), new ThreadPoolExecutor.AbortPolicy());

}

}

}

}

}

3.3 线程池运行测试示例

./src/main/java/com/ljq/demo/concurrent/DrinkThreadPoolDemo.java

1

package com.ljq.demo.concurrent;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import cn.hutool.core.thread.ThreadUtil;

import com.ljq.demo.util.ThreadPoolUtil;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

/**

* @Description: 喝酒线程池示例

* @Author: junqiang.lu

* @Date: 2021/5/14

*/

@Slf4j

public class DrinkThreadPoolDemo {

public static void main(String[] args) {

manualThreadPool();

huToolThreadUtil();

localThreadPoolUtil();

}

/**

* 手动创建线程池

*/

public static void manualThreadPool() {

// 创建线程池

ThreadPoolExecutor executor = new ThreadPoolExecutor(2,10,100,

TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1000), ThreadFactoryBuilder.create().build(),

new ThreadPoolExecutor.AbortPolicy());

// 总杯数

int totalCup = 100;

int cupNumber;

for (int i = 1; i <= totalCup; i++) {

try {

cupNumber = executor.submit(new DrinkTask(i)).get();

log.info("manual cupNumber: {}", cupNumber);

} catch (InterruptedException e) {

log.error("线程池执行错误", e);

} catch (ExecutionException e) {

log.error("武松喝醉了", e);

}

}

// 关闭线程池

executor.shutdown();

}

/**

* 使用 hutool 线程工具类

* (线程池不会自动销毁)

*/

public static void huToolThreadUtil() {

// 总杯数

int totalCup = 100;

int cupNumber;

for (int i = 1; i <= totalCup; i++) {

try {

cupNumber = ThreadUtil.execAsync(new DrinkTask(i)).get();

log.info("hutool cupNumber: {}", cupNumber);

} catch (InterruptedException e) {

log.error("线程池执行错误", e);

} catch (ExecutionException e) {

log.error("武松喝醉了", e);

}

}

}

/**

* 本地线程池工具类

*/

public static void localThreadPoolUtil() {

// 总杯数

int totalCup = 100;

int cupNumber;

for (int i = 1; i <= totalCup; i++) {

try {

cupNumber = ThreadPoolUtil.executeAsync(new DrinkTask(i)).get();

log.info("local cupNumber: {}", cupNumber);

} catch (InterruptedException e) {

log.error("线程池执行错误", e);

} catch (ExecutionException e) {

log.error("武松喝醉了", e);

}

}

ThreadPoolUtil.shutdown();

}

}

3.4 部分执行日志

2021-05-14 16:50:58:890 [pool-4-thread-1] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[1]杯酒

2021-05-14 16:50:58:992 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 1

2021-05-14 16:50:58:993 [pool-4-thread-2] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[2]杯酒

2021-05-14 16:50:59:094 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 2

2021-05-14 16:50:59:095 [pool-4-thread-3] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[3]杯酒

2021-05-14 16:50:59:199 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 3

2021-05-14 16:50:59:200 [pool-4-thread-4] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[4]杯酒

2021-05-14 16:50:59:301 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 4

2021-05-14 16:50:59:301 [pool-4-thread-1] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[5]杯酒

2021-05-14 16:50:59:401 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 5

... ...

2021-05-14 16:51:08:694 [pool-4-thread-4] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[96]杯酒

2021-05-14 16:51:08:794 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 96

2021-05-14 16:51:08:795 [pool-4-thread-1] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[97]杯酒

2021-05-14 16:51:08:897 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 97

2021-05-14 16:51:08:897 [pool-4-thread-2] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[98]杯酒

2021-05-14 16:51:08:998 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 98

2021-05-14 16:51:08:999 [pool-4-thread-3] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[99]杯酒

2021-05-14 16:51:09:101 [main] INFO com.ljq.demo.concurrent.DrinkThreadPoolDemo(DrinkThreadPoolDemo.java 82) -local cupNumber: 99

2021-05-14 16:51:09:102 [pool-4-thread-4] INFO
com.ljq.demo.concurrent.DrinkTask(DrinkTask.java 26) -武松喝完了第[100]杯酒

相关推荐

全面解读 Java 日志框架(一)(java项目中日志管理怎么做)

随着互联网和大数据的蓬勃发展,分布式日志系统以及日志分析系统得到了广泛地应用。目前,几乎在所有应用程序中,都会用到各种各样的日志框架来记录程序的运行信息。鉴于此,作为工程师,十分有必要熟悉主流的日志记...

Java 线程池规范使用示例(java线程池入门)

1摘要Java线程池在批量处理的场景中应用广泛。常见的四种创建线程池的方法:newSingleThreadExecutor,newFixedThreadPool,newCachedThreadPo...

还在为烂代码头疼?SonarQube + 阿里 P3C 助力规范代码

前言我们在使用SonarQube做Java静态代码扫描的时候必须使用同一套规范,而SonarQube默认使用的是它自带的规范(SonarQube称为规则),而我们都知道在国内阿里在Ja...

阿里巴巴Java开发规范(9):SQL语句

几乎所有大厂都会对代码规范有着严格要求,以确保多人协作开发出来的代码质量有统一的标准。在Java开发领域,《阿里巴巴Java开发手册》被开发者们广泛学习和应用。原手册内容较多,本文仅列出SQL语句方面...

有了这个插件,再也不用担心代码不合规范了

JAVA开发工具IDEA,这是宇宙最好用的JavaIDE,没有之一!IDEA的开放能力做的还不错,可以添加很多插件,让我们的很多开发工作更加便捷。我装的插件其实没几个,但有一款是一直以来在用的...

Executor(executor提供了哪几种线程池)

一、前言JDK1.5中提供了Executor接口,处于java.util.concurrent包下;创建线程的几种方法创建子类继承Thread类(Thread类实现了Runable接口)并重写run(...

干掉 PowerDesigner!这款国人开源的数据库设计工具真香

当我们在项目开发初期时,往往需要设计大量的表,此时使用数据库设计工具就会比较高效!今天给大家推荐一款国人开源的数据库设计工具chiner,界面漂亮,功能强大,希望对大家有所帮助!聊聊PowerDesi...

AI实用指南:Rules编写规则详解,从前端到后端的技术栈全覆盖

在AI驱动的开发时代,掌握如何与AI助手高效协作已成为工程师的必备技能。本文全面梳理了不同技术领域的AI编程规则,帮助你划定合理边界,提升开发效率。一、AI编程通用规则1.明确任务边界在使用AI辅助...

为什么阿里巴巴Java开发手册禁止使用Executors创建线程池?

在Java并发编程中,线程池是提高系统性能的关键组件,而Executors工厂方法提供了创建线程池的便捷途径。许多开发者习惯性地使用Executors.newFixedThreadPool()或Exe...

阿里巴巴Java开发手册(详尽版),pdf

前言:不知不觉间,2022年已经过了一半了,作为技术圈中你,准备好迎接最新的变化了吗?在本文中,我们将以编程界最常用的编程语言Java为例,分享最为主流的技术与工具。目录:一、编程规约(一)命...

分享,阿里巴巴Java开发手册 v1.2.0版

阿里巴巴作为国内互联网的领军企业,不知道他的java开发手册是什么样子的,有什么规范。今天就给大家看下,文末附下载链接。今年年初,《阿里巴巴Java开发手册》正式发布,阿里官方Java代码规范标准首次...

Microsoft 365应用将取代Office应用,成为体验微软服务的新中心

IT之家10月13日消息,你可能对手机或Windows设备上的Office应用很熟悉,但很快这些应用就要改名了。在2022年的Ignite会议上,微软宣布了一个新的Micro...

如何通过系统U盘安装Windows 和安装软件一样简单

上一期告诉大家如何用最简单的方法制作Windows系统U盘,感兴趣的朋友可以点此跳转。这一期我们来聊一聊用之前制作的Windows系统U盘安装Windows系统。其实安装Windows系统和安装软件一...

Windows 10 版本推荐与选择指南(win10选择什么版本好?)

Windows10的稳定性和适用性会因版本不同而有所差异,用户需依据自身需求以及硬件配置来合理选择。以下综合多方信息,为您推荐合适的Windows10版本并进行详细分析。一、推荐版本及适用场...

好软推荐:简单几步,让 Windows 的字体变成 Mac一样好看

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:Stark-C大家好,我是Stark-C。我想用过苹果Mac电脑的小伙伴都知道,苹果Mac不光系统的UI非常漂亮,而且它上面的字体也是非常的...