目录
一、ExecutorService:通用线程池任务调度
常见使用方式:
优点:
适用场景:
注意事项:
二、Fork/Join 框架:分治法并行计算
示例:用 Fork/Join 计算数组和
三、ExecutorService vs Fork/Join:如何选择?
简单判断标准:
四、实际建议
首页 Java java教程 Java并发公用事业:执行人员服务和叉/加入

Java并发公用事业:执行人员服务和叉/加入

Aug 03, 2025 am 01:54 AM
java 并发

ExecutorService适用于独立任务的异步执行,如I/O操作或定时任务,使用线程池管理并发,通过submit提交Runnable或Callable任务,并用Future获取结果,需注意无界队列风险和显式关闭线程池;2. Fork/Join框架专为可拆分的CPU密集型任务设计,基于分治法和工作窃取算法,通过RecursiveTask或RecursiveAction实现任务递归拆分,由ForkJoinPool调度执行,适合大数组求和、排序等场景,需合理设置拆分阈值避免开销;3. 选择依据:独立任务优先用ExecutorService,可递归拆分的计算任务用Fork/Join;4. 实际应用中,Web异步处理推荐ExecutorService,大数据计算可选Fork/Join或parallelStream,两者互补,正确使用可提升并发效率与可控性。

Java Concurrency Utilities: ExecutorService and Fork/Join

Java 的并发工具包 java.util.concurrent 提供了多种高级并发机制,其中 ExecutorServiceFork/Join 框架 是处理多线程任务最常用的两种工具。它们各有适用场景,理解它们的区别和使用方式,能帮助我们写出更高效、更易维护的并发程序。

Java Concurrency Utilities: ExecutorService and Fork/Join

一、ExecutorService:通用线程池任务调度

ExecutorService 是 Java 并发编程中最基础也最常用的线程池工具,它把任务的提交和执行解耦,开发者只需提交 RunnableCallable 任务,由线池负责调度执行。

常见使用方式:

ExecutorService executor = Executors.newFixedThreadPool(4);

// 提交 Runnable(无返回值)
executor.submit(() -> System.out.println("Hello from thread"));

// 提交 Callable(有返回值)
Future<Integer> future = executor.submit(() -> {
    return 42;
});

// 获取结果(阻塞)
Integer result = future.get();

// 关闭线程池
executor.shutdown();

优点:

  • 简单易用,适合大多数异步任务场景
  • 支持定时任务(ScheduledExecutorService
  • 可管理线程生命周期,避免资源泄漏

适用场景:

  • 处理独立的、长时间运行的任务(如网络请求、数据库操作)
  • 需要控制并发数的批量任务
  • 定时任务调度

注意事项:

  • Executors.newFixedThreadPool() 使用无界队列,可能导致内存溢出
  • 必须调用 shutdown() 避免程序无法退出
  • Future.get() 是阻塞操作,需注意超时设置

二、Fork/Join 框架:分治法并行计算

Fork/Join 是为“分而治之”(divide and conquer)算法设计的专用框架,特别适合可以递归拆分的大任务,比如归并排序、数组求和、树遍历等。

Java Concurrency Utilities: ExecutorService and Fork/Join

核心类是 ForkJoinPoolRecursiveTask(有返回值)或 RecursiveAction(无返回值)。

示例:用 Fork/Join 计算数组和

class SumTask extends RecursiveTask<Long> {
    private final long[] array;
    private final int start, end;
    private static final int THRESHOLD = 1000;

    public SumTask(long[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            // 小任务直接计算
            long sum = 0;
            for (int i = start; i < end; i  ) {
                sum  = array[i];
            }
            return sum;
        } else {
            // 拆分任务
            int mid = (start   end) / 2;
            SumTask left = new SumTask(array, start, mid);
            SumTask right = new SumTask(array, mid, end);

            left.fork();  // 异步执行左任务
            long rightResult = right.compute(); // 当前线程执行右任务
            long leftResult = left.join();      // 等待左任务结果

            return leftResult   rightResult;
        }
    }
}

// 使用
ForkJoinPool pool = new ForkJoinPool();
long[] data = new long[100_000];
Arrays.fill(data, 1);
Long result = pool.invoke(new SumTask(data, 0, data.length));

优点:

  • 使用工作窃取(work-stealing)算法,空闲线程会从其他线程的任务队列尾部“偷”任务,提高 CPU 利用率
  • 默认线程数等于 CPU 核心数,适合 CPU 密集型任务
  • 递归任务拆分自然,代码结构清晰

适用场景:

  • 可拆分的计算密集型任务(如排序、搜索、数值计算)
  • 数据量大但逻辑可递归分解的问题

注意事项:

  • 不适合 I/O 密集型任务(如网络、文件读写)
  • 拆分粒度要合理,太细会增加调度开销,太粗无法充分利用多核
  • 递归深度过高可能导致栈溢出(但通常不会,因为任务在堆上)

三、ExecutorService vs Fork/Join:如何选择?

对比项ExecutorServiceFork/Join
适用任务类型I/O 密集型、独立任务CPU 密集型、可拆分任务
调度方式固定线程池,任务排队工作窃取,动态负载均衡
任务模型Runnable / CallableRecursiveTask / RecursiveAction
线程数可配置(通常大于核心数)默认为 CPU 核心数
使用复杂度简单直接需要合理拆分任务

简单判断标准:

  • 如果任务是“一堆独立工作”,用 ExecutorService
  • 如果任务是“一个大问题可以拆成小问题”,用 Fork/Join

四、实际建议

  • 对于 Web 服务中的异步处理(如发邮件、记录日志),优先使用 ExecutorService
  • 对于大数据量的计算(如统计、分析、图像处理),考虑 Fork/Join
  • Java 8 的 parallelStream() 底层就是 Fork/Join,比如:
    long sum = Arrays.stream(largeArray).parallel().sum();

    这种写法简洁,但要注意副作用和调试困难的问题。

    Java Concurrency Utilities: ExecutorService and Fork/Join

    基本上就这些。两种工具不是替代关系,而是互补的。用对工具,才能让并发既高效又可控。

    以上是Java并发公用事业:执行人员服务和叉/加入的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

Rimworld Odyssey温度指南和Gravtech
1 个月前 By Jack chen
初学者的Rimworld指南:奥德赛
1 个月前 By Jack chen
PHP变量范围解释了
4 周前 By 百草
撰写PHP评论的提示
3 周前 By 百草
在PHP中评论代码
3 周前 By 百草

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Laravel 教程
1604
29
PHP教程
1509
276
Edge PDF查看器不起作用 Edge PDF查看器不起作用 Aug 07, 2025 pm 04:36 PM

testthepdfinanotherapptoderineiftheissueiswiththefileoredge.2.enablethebuilt inpdfviewerbyTurningOff“ eflblyopenpenpenpenpenpdffilesexternally”和“ downloadpdffiles” inedgesettings.3.clearbrowsingdatainclorwearbrowsingdataincludingcookiesandcachedcachedfileresteroresoreloresorelorsolesoresolesoresolvereresoreorsolvereresoreolversorelesoresolvererverenn

如何在Java中实现简单的TCP客户端? 如何在Java中实现简单的TCP客户端? Aug 08, 2025 pm 03:56 PM

Importjava.ioandjava.net.SocketforI/Oandsocketcommunication.2.CreateaSocketobjecttoconnecttotheserverusinghostnameandport.3.UsePrintWritertosenddataviaoutputstreamandBufferedReadertoreadserverresponsesfrominputstream.4.Usetry-with-resourcestoautomati

用Docker将Java应用程序部署到Kubernetes 用Docker将Java应用程序部署到Kubernetes Aug 08, 2025 pm 02:45 PM

容器化Java应用:创建Dockerfile,使用基础镜像如eclipse-temurin:17-jre-alpine,复制JAR文件并定义启动命令,通过dockerbuild构建镜像并用dockerrun测试本地运行。2.推送镜像到容器注册表:使用dockertag标记镜像并推送到DockerHub等注册表,需先登录dockerlogin。3.部署到Kubernetes:编写deployment.yaml定义Deployment,设置副本数、容器镜像和资源限制,编写service.yaml创建

VS代码快捷方式专注于Explorer面板 VS代码快捷方式专注于Explorer面板 Aug 08, 2025 am 04:00 AM

VSCode中可通过快捷键快速切换面板与编辑区。要跳转至左侧资源管理器面板,使用Ctrl Shift E(Windows/Linux)或Cmd Shift E(Mac);返回编辑区可用Ctrl `或Esc或Ctrl 1~9。相比鼠标操作,键盘快捷键更高效且不打断编码节奏。其他技巧包括:Ctrl KCtrl E聚焦搜索框,F2重命名文件,Delete删除文件,Enter打开文件,方向键展开/收起文件夹。

修复:Windows Update无法安装 修复:Windows Update无法安装 Aug 08, 2025 pm 04:16 PM

runthewindowsupdatetrubloubleshooterviaSettings>更新&安全> is esseShootsoAtomationfixCommonissues.2.ResetWindowSupDateComponentsByStoppingRealatedServices,RenamingTheSoftWaredWaredWaredSoftwaredSistribution andCatroot2Folders,intrestrestartingthertingthertingtherserviceSteStoceTocle

Java对象的序列化过程是什么? Java对象的序列化过程是什么? Aug 08, 2025 pm 04:03 PM

JavaserializationConvertSanObject'SstateIntoAbyTeSteAmForStorageorTransermission,andDeserializationReconstructstheObjectStheObjectFromThstream.1.toenableserialization,aclassMustimustimplementTheSerializableizableface.2.UseObjectObjectObjectObjectOutputputputputputtreamToserialializeanobectizeanobectementeabectenobexpent,savin

如何在Java中使用一个时循环 如何在Java中使用一个时循环 Aug 08, 2025 pm 04:04 PM

AwhileloopinJavarepeatedlyexecutescodeaslongastheconditionistrue;2.Initializeacontrolvariablebeforetheloop;3.Definetheloopconditionusingabooleanexpression;4.Updatethecontrolvariableinsidethelooptopreventinfinitelooping;5.Useexampleslikeprintingnumber

python numpy线性代数示例 python numpy线性代数示例 Aug 07, 2025 pm 04:52 PM

NumPy是Python中进行科学计算的核心库,擅长处理线性代数运算,提供高效的ndarray数组和numpy.linalg模块中的函数。1.使用np.linalg.solve(A,b)可求解线性方程组Ax=b,得到解向量x;2.矩阵转置通过A.T实现;3.矩阵乘法可用np.dot(A,B)或A@B;4.矩阵逆通过np.linalg.inv(A)计算,需确保矩阵可逆;5.行列式由np.linalg.det(A)给出;6.特征值与特征向量通过np.linalg.eig(A)求得,特征向量已归一化;

See all articles