百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Java 线程池创建方式大揭秘!互联网大厂后端开发必看

moboyou 2025-06-05 16:49 20 浏览

你在互联网大厂做后端开发时,在使用 Java 线程池方面,有没有遇到过不知道该怎么创建的情况呢?项目需求一来,多线程任务一布置,线程池该如何正确创建,成了很多开发者头疼的问题。今天,咱们就深入聊聊 Java 中线程池的创建方式,帮你彻底解决这个困扰!

互联网大厂后端开发为什么离不开线程池?

在互联网大厂的后端开发场景中,高并发、大数据量处理是家常便饭。以电商平台的大促活动为例,海量用户同时下单、查询订单信息,服务器需要同时处理成千上万的请求。这时候,线程池就显得尤为重要。如果没有合理使用线程池,要么创建过多线程导致资源耗尽,服务器崩溃;要么线程数量不足,任务堆积,用户等待时间过长,严重影响用户体验。而且,Java 作为互联网后端开发的主流语言之一,其线程池机制是保障程序高效稳定运行的关键。但很多开发者对于线程池的创建,仅仅停留在一知半解的层面,这就很容易在实际开发中埋下隐患。

Java 线程池创建方式详解

Java 中线程池的创建方式主要有以下几种:

使用 Executors 工厂类创建

FixedThreadPool

通过
Executors.newFixedThreadPool(int nThreads)方法创建,它会创建一个固定大小的线程池,池中线程数量固定不变。当有新任务提交时,如果线程池中有空闲线程,就会立即执行任务;如果没有空闲线程,任务会被暂存到一个阻塞队列中,等待有线程空闲时再执行。

示例:假设我们有一个电商订单处理系统,需要同时处理 10 个订单的支付请求,每个支付请求都需要一个线程来处理。为了避免线程过多导致资源竞争,我们可以使用 FixedThreadPool 来创建一个固定大小为 10 的线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FixedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 20; i++) {
            final int orderId = i;
            executorService.submit(() -> {
                // 模拟处理订单支付逻辑
                System.out.println("处理订单 " + orderId + " 的支付请求");
            });
        }
        executorService.shutdown();
    }
}

这种线程池适用于处理固定数量并发任务的场景,比如数据库连接池,保证固定数量的线程同时访问数据库,避免资源竞争。

CachedThreadPool

使用
Executors.newCachedThreadPool()创建,它是一个可缓存的线程池。如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程。它比较适合处理执行时间短、突发性大量请求的任务。

示例:在一个日志收集系统中,会不定期有大量的日志记录任务产生。我们可以使用 CachedThreadPool 来处理这些任务。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CachedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            final int logId = i;
            executorService.submit(() -> {
                // 模拟记录日志逻辑
                System.out.println("记录日志 " + logId);
            });
        }
        executorService.shutdown();
    }
}

任务执行完线程就可以被回收,下次有新任务再来时又能快速创建新线程处理。

SingleThreadExecutor

通过
Executors.newSingleThreadExecutor()创建,它只有一个工作线程来执行任务。所有任务按照提交顺序依次执行,保证任务执行的顺序性。

示例:在文件按顺序读写操作的场景中,使用 SingleThreadExecutor 能确保数据的读写顺序。比如,我们要按顺序读取一系列文本文件的内容。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadExecutorExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        String[] fileNames = {"file1.txt", "file2.txt", "file3.txt"};
        for (String fileName : fileNames) {
            final String name = fileName;
            executorService.submit(() -> {
                // 模拟按顺序读取文件内容逻辑
                System.out.println("读取文件 " + name + " 的内容");
            });
        }
        executorService.shutdown();
    }
}

ScheduledThreadPool

使用
Executors.newScheduledThreadPool(int corePoolSize)创建,它可以实现定时任务和周期性任务的执行。

示例:在电商系统中,每天凌晨 2 点需要统计前一天的销售数据。我们可以使用 ScheduledThreadPool 来实现这个定时任务。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            // 模拟统计销售数据逻辑
            System.out.println("统计销售数据");
        }, 0, 1, TimeUnit.DAYS);
    }
}

通过schedule()方法可以延迟执行任务,scheduleAtFixedRate()和scheduleWithFixedDelay()方法可以实现周期性任务的执行。

通过 ThreadPoolExecutor 类手动创建

ThreadPoolExecutor 是创建线程池的核心类,通过它我们可以更灵活地配置线程池的参数。它的构造函数如下:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
  • corePoolSize:核心线程数,线程池创建后默认会创建的线程数量,即使这些线程处于空闲状态,也不会被销毁(除非设置了allowCoreThreadTimeOut为true)。
  • maximumPoolSize:最大线程数,线程池中允许存在的最大线程数量。当任务队列满了且工作线程数小于最大线程数时,线程池会创建新的线程来处理任务。
  • keepAliveTime:空闲线程的存活时间。当线程池中的线程数量大于核心线程数时,如果某个线程空闲时间超过keepAliveTime,就会被销毁,直到线程池中的线程数量等于核心线程数。
  • unit:keepAliveTime的时间单位,如TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)等。
  • workQueue:任务队列,用于存放等待执行的任务。常见的有ArrayBlockingQueue(有界队列)、LinkedBlockingQueue(无界队列)等。
  • threadFactory:线程工厂,用于创建线程,一般使用默认的线程工厂即可,也可以自定义线程工厂来设置线程的名称、优先级等属性。
  • handler:拒绝策略,当任务队列已满且线程数达到最大线程数时,新提交的任务会被拒绝,此时就需要通过拒绝策略来处理这些被拒绝的任务。常见的拒绝策略有AbortPolicy(抛出异常)、CallerRunsPolicy(在调用者线程中执行任务)、DiscardPolicy(丢弃任务)、DiscardOldestPolicy(丢弃队列中最老的任务,然后重新提交当前任务)。

示例:我们创建一个线程池,核心线程数为 5,最大线程数为 10,空闲线程存活时间为 60 秒,任务队列使用有界的ArrayBlockingQueue,容量为 20,拒绝策略采用CallerRunsPolicy。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(20);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5,
                10,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        for (int i = 0; i < 50; i++) {
            final int taskId = i;
            threadPoolExecutor.submit(() -> {
                // 模拟任务执行逻辑
                System.out.println("执行任务 " + taskId);
            });
        }
        threadPoolExecutor.shutdown();
    }
}

手动创建线程池虽然相对复杂,但却能让我们根据具体的业务场景,精准地配置各项参数,以达到最佳的性能和资源利用效果。

总结

以上就是 Java 中线程池常见的创建方式。在互联网大厂后端开发中,掌握这些创建方式,合理配置线程池参数,能让你的程序在高并发场景下更加稳定、高效地运行。希望大家都能熟练运用线程池,在项目开发中少踩坑!如果你在实际使用线程池的过程中有任何问题,或者有独特的经验,欢迎在评论区留言分享,咱们一起交流探讨,共同进步!

相关推荐

python新手学习常见数据类型——数字

Python支持三种不同的数值类型:整型(int)、浮点型(float)、复数(complex)创建数字:a=1b=2.7c=8+4j删除数字:a=1b=2.7c=8+4...

只用一个套路公式,给 Excel 中一列人员设置随机出场顺序

很多同学会觉得Excel单个案例讲解有些碎片化,初学者未必能完全理解和掌握。不少同学都希望有一套完整的图文教学,从最基础的概念开始,一步步由简入繁、从入门到精通,系统化地讲解Excel的各个知...

Excel神技 TIME函数:3秒搞定时间拼接!职场人必学的效率秘籍

你是否经常需要在Excel中手动输入时间,或者从不同单元格拼接时、分、秒?今天我要揭秘一个超实用的Excel函数——TIME函数,它能让你3秒内生成标准时间格式,彻底告别繁琐操作!一、TIME函数基础...

销售算错数被批?97 Excel 数字函数救场,3 步搞定复杂计算

销售部小张被老板当着全部门骂。上季度销售额汇总,他把38652.78算成36852.78,差了1800块。财务对账时发现,整个部门的提成表都得重算。"连个数都算不对,还做什么销售?&...

如何使用Minitab 1分钟生成所需要的SPC数据

打开Minitab,“计算”-“随机数据”-“正太”,因为不好截图,使用的是拍照记录的方式.再要生产的行数中,填写125,可以按照要求,有些客户要求的是100个数据,就可以填写100...

验证码,除了 12306,我还没有服过谁

为了防止暴力注册或爬虫爬取等机器请求,需要验证操作者是人还是机器,便有了验证码这个设计。本文作者主要介绍了如何使用Axure来设计一个动态的图形验证码,一起来学习一下吧。在软件设计中,为了防止暴力...

零基础也能学会的9个Excel函数,小白进阶必备

今天给大家分享一些常用的函数公式,可以有效地解决Excel中办公所需,0基础也可以轻松学会。建议收藏,在需要的时候可以直接套用函数。1、计算排名根据总和,计算学生成绩排名。函数公式=RANK(E2,$...

[office] excel表格数值如何设置_excel表格怎样设置数值

excel表格数值如何设置  因为电子表格应用程序是用来处理数值数据的,所以数值格式可能是工作表中最关键的部分,格式化数值数据的方式由用户决定,但在每个工作簿的工作表之间应使用一致的处理数字的方法。...

Excel最常用的5个函数!会用最后一个才是高手

是不是在处理Excel数据时,面对繁琐的操作烦恼不已?手动操作不仅耗时费力,还容易出错。别担心,表姐这就为你揭秘Excel中几个超实用的函数,让数据处理变得轻松高效!表姐整理了552页《Office从...

新手必会的53个Excel函数_惊呆小伙伴的全套excel函数技能

(新手入门+进阶+新函数)一、新手入门级(24个)1、Sum函数:求和=Sum(区域)2、Average函数:求平均值=Average(区域)3、Count函数:数字个数=Count(区域)4、Cou...

打工人私藏的4个Excel函数秘籍,效率提升3.7%

小伙伴们好啊,今天咱们分享几个常用函数公式的典型应用。合并内容如下图,希望将B列的姓名,按照不同部门合并到一个单元格里。=TEXTJOIN(",",1,IF(A$2:A$15=D2,B...

Excel偷偷更新的8个函数!原来高手都在用这些隐藏技能

领导突然要销售数据,你手忙脚乱筛选到眼花...同事3分钟搞定的报表,你折腾半小时还在填充公式...明明用了VLOOKUP,却总显示#N/A错误...别慌!今天教你的8个动态数组函数,就像给Excel装...

Excel表格随机函数怎么用?讲解三种随机函数在不同场景的应用

excel随机函数,其特点是能够生成一组随机数字,根据不同需求,还能批量生成小数位和整数,及指定行数和列数,或指定区间范围内的数字。这里根据需求,作者设置了三个问题,第1个是随机生成0至1之间的数字...

单纯随机抽样该如何进行?_单纯随机抽样的适用范围及注意事项

在数据分析中,抽样是指从全部数据中选择部分数据进行分析,以发掘更大规模数据集中的有用信息。在收集数据过程中,绝大多数情况下,并不采取普查的方式获取总体中所有样本的数据信息,而是以各类抽样方法抽取其中若...

随机函数在Excel中的应用_随机函数在excel中的应用实例

【分享成果,随喜正能量】职场,如果你没有价值,那么你随时可能被取代;如果你的价值不如别人,那么社会也不会惯你,你将被无情地淘汰掉。不管什么时候,你一定要学会构建自己的价值。每个人都应该思考这个问题:我...