ExecutorService

article/2025/9/9 2:26:40

本文翻译自http://tutorials.jenkov.com/java-util-concurrent/executorservice.html,人工翻译,仅供学习交流。

ExecutorService

java.util.concurrent.ExecutorService接口是一种能够在后台并发执行任务的异步执行机制。本文中,我将会介绍如何创建ExecutorService,如何向它提交要执行的任务,如何查看这些任务的结果以及当需要时,如何再次关闭ExecutorService。

任务委派

下面的图表演示了一个线程如何将一个任务委托给Java ExecutorService进行异步
将任务委托给ExecutorService进行异步执行的线程
一旦线程将任务委托给ExecutorService,线程继续它自己的执行,独立于该任务的执行。ExecutorService并发地执行任务,独立于提交的线程。

Java ExecutorService示例

在我们深入到ExecutorService之前,先看个样例。下面是一个简单的Java ExecutorService示例:

ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();

首先,使用Executors newFixedThreadPool()工厂方法创建ExecutorService,这将创建一个线程池,其中有10个线程在执行任务。
其次,Runnable接口的匿名实现被传递给execute()方法。这将导致ExecutorService中的一个线程执行Runnable。
在本教程中,您将看到更多关于如何使用ExecutorService的示例。这个例子只是提供给你一个如何使用一个ExecutorService在后台执行任务的快速概述。

Java ExecutorService实现类

Java ExecutorService非常类似于线程池,concurrent包中ExecutorService接口的实现也是一个线程池实现。如果您想了解如何在内部实现ExecutorService接口,阅读上面的教程。
因为ExecutorService是一个接口,为了使用它,你需要它的实现类。ExecutorService在java.util.concurrent包中有以下实现:

  • ThreadPoolExecutor
  • ScheduledThreadPoolExecutor

创建ExecutorService

如何创建ExecutorService取决于您使用的实现类。你也可以使用Executors工厂类来创建ExecutorService实例。下面是一些创建ExecutorService的示例:

ExecutorService executorService1 = Executors.newSingleThreadExecutor();ExecutorService executorService2 = Executors.newFixedThreadPool(10);ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

ExecutorService用法

有几种不同的方法可以将任务委托给ExecutorService执行:

  • execute(Runnable)
  • submit(Runnable)
  • submit(Callable)
  • invokeAny(…)
  • invokeAll(…)
    我将在下面的部分中介绍这些方法。

Execute Runnable

ExecutorService execute(Runnable) 方法获取一个runnable对象,然后异步执行它。下面是一个使用ExecutorService执行Runnable的例子:

ExecutorService executorService = Executors.newSingleThreadExecutor();executorService.execute(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});executorService.shutdown();

这种操作没有办法获得执行的Runnable的结果。如果需要结果,必须使用Callable(将在下面的部分中进行解释)。

Submit Runnable

ExecutorService submit(Runnable)方法也是获取Runnable实现,但会返回一个Future对象。这个Future对象可以用来检查Runnable是否已经完成执行。下面是一个Java ExecutorService submit()的例子:

Future future = executorService.submit(new Runnable() {public void run() {System.out.println("Asynchronous task");}
});future.get();  //returns null if the task has finished correctly.

submit()方法返回一个Java Future对象,该对象可用于检查Runnable是否完成。

Submit Callable

ExecutorService submit(Callable) 和 submit(Runnable)是相似的,除了用Callable对象代替Runnable对象。稍后将解释可调用对象和可运行对象之间的确切区别。Callable的结果可以通过submit(Callable) 方法返回的Java Future对象获得。下面是ExecutorService调用的示例:

Future future = executorService.submit(new Callable(){public Object call() throws Exception {System.out.println("Asynchronous Callable");return "Callable Result";}
});System.out.println("future.get() = " + future.get());

上面的代码示例将输出如下:

Asynchronous Callable
future.get() = Callable Result

invokeAny()

invokeAny()方法接受一组Callable对象,调用此方法不会返回Future,但会返回一个Callable对象的结果。您无法保证得到哪个Callable结果,只有一个能完成的。
如果一个Callable完成,那么从invokeAny()返回一个结果,然后其余的Callable实例会被取消。
如果其中一个任务完成(或抛出异常),其他的Callable都被取消了。下面是一个代码示例:

ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() {public String call() throws Exception {return "Task 1";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 2";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 3";}
});String result = executorService.invokeAny(callables);System.out.println("result = " + result);executorService.shutdown();

这个代码示例将打印出给定集合中的一个Callable对象返回的对象,我试着运行了几次,结果发生了变化。有时是“任务1”,有时是“任务2”。

invokeAll()

invokeAll()方法调用作为参数传递给它的集合中的所有Callable对象。invokeAll()返回一个Future对象列表,通过该列表可以获得每个Callable的执行结果。
请记住,任务可能会由于异常而结束,所以它可能没有成功。在Future上没有办法区分这两者。下面是一个代码示例:

ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() {public String call() throws Exception {return "Task 1";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 2";}
});
callables.add(new Callable<String>() {public String call() throws Exception {return "Task 3";}
});List<Future<String>> futures = executorService.invokeAll(callables);for(Future<String> future : futures){System.out.println("future.get = " + future.get());
}executorService.shutdown();

Runnable vs. Callable

Runnable接口与Callable接口非常相似。Runnable接口是可以由线程或 ExecutorService并发执行的任务,Callable只能由ExecutorService执行。两个接口都只有一个方法。不过,Callable和Runnable接口之间有一个微小的区别,在接口声明里更容易看到。首先是Runnable接口声明:

public interface Runnable {public void run();
}

下面是Callable接口声明:

public interface Callable{public Object call() throws Exception;
}

Runnable run()方法和Callable call()方法之间的主要区别是call()方法可以从方法调用中返回一个Object。call()和run()之间的另一个区别是call()可以抛出异常,,而run()不能(除了未检查的异常- RuntimeException的子类)。
如果需要将任务提交给Java ExecutorService,并且需要任务的结果,然后你需要让你的任务实现Callable接口。否则任务也可以只实现Runnable接口。

Cancel Task

当任务已经提交时,可以通过调用返回的Future的cancel()方法来取消提交给Java ExecutorService的任务。如果任务还没有开始,才可能取消任务。这里有一个样例:

future.cancel();

ExecutorService 关闭

当你使用完Java ExecutorService时,你应该关闭它,因此线程不会继续运行。如果你的应用程序是通过main()方法启动的,你的主线程退出你的应用程序,如果您的应用程序中有一个活动的ExexutorService,应用程序将继续运行。这个ExecutorService中的活动线程会阻止JVM关闭。

shutdown()

要终止ExecutorService内部的线程,可以调用它的shutdown()方法。ExecutorService不会立即关闭,但它将不再接受新的任务,一旦所有线程都完成了当前任务,ExecutorService就会关闭。调用shutdown()之前提交给ExecutorService的所有任务都是执行完成的。下面是一个执行Java ExecutorService关闭的示例:

executorService.shutdown();

shutdownNow()

如果您想立即关闭ExecutorService,可以调用shutdownNow()方法,这将尝试立即停止所有正在执行的任务,并跳过所有提交但未处理的任务。对于正在执行的任务没有任何保证,也许他们会停止,也许会执行到最后。这是最好的尝试。下面是调用ExecutorService shutdownNow的示例:

executorService.shutdownNow();

awaitTermination()

直到ExecutorService已经完全关闭,或者直到发生给定的超时,ExecutorService awaitterminate()方法将阻塞调用它的线程。通常在调用shutdown()或shutdownNow()之后调用awaitterminate()方法。下面是调用ExecutorService awaitTermination()的示例:

executorService.shutdown();executorService.awaitTermination(10_000L, TimeUnit.MILLISECONDS );

下一节:Java Callable


http://chatgpt.dhexx.cn/article/RJxSEW60.shtml

相关文章

Executor概述

在Java类库中&#xff0c;任务执行的主要抽象不是Thread&#xff0c;而是Executor。 public interface Executor {void execute(Runnable command); }它为灵活且强大的异步任务执行框架提供了基础&#xff0c;该框架能支持多种不同类型的任务执行策略。它提供了一种标准的方法…

Executor框架简介

Executor系统中&#xff0c;将线程任务提交和任务执行进行了解耦的设计; 线程被一对一映射为服务所在操作系统线程&#xff0c;启动时会创建一个操作系统线程&#xff1b;当该线程终止时&#xff0c;这个操作系统线程也会被回收 Executor框架包含的核心接口和主要的实现类 具体…

Executors 源码解析(JDK8)

前言 本文隶属于专栏《100个问题搞定Java并发》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见100个问题搞定Java并发 正文 类注释 /*** Factory and util…

Executor框架

转载请以链接形式标明出处&#xff1a; 本文出自:103style的博客 Java并发编程的艺术笔记 并发编程的挑战Java并发机制的底层实现原理Java内存模型Java并发编程基础Java中的锁的使用和实现介绍Java并发容器和框架Java中的12个原子操作类介绍Java中的并发工具类Java中的线程池E…

Executor执行器

分为四个模块&#xff1a; 1.动态代理MapperProxy 2.SQL会话SqlSesson 3.执行器Executor 4.JDBC处理器StatementHandler 现讲述为SQL会话与执行器 一、SQL会话SqlSesson 该门面模式提供一个统一的门面接口API 该模式提供的一个基本API为增删改查&#xff0c;还会提供提…

Java并发多线程编程——Executors类

目录 一、Executors的理解二、Executors类图结构二、Executors常用的方法三、线程池的创建分为两种方式&#xff08;主要介绍通过Executors类创建的方式&#xff09;1、newFixedThreadPool方法示例2、newSingleThreadExecutor方法示例3、newCachedThreadPool方法4、newSchedule…

Executors一篇就够

Executors框架包含的内容十分的多&#xff1a;看图&#xff1a; 一、各个接口的作用 按照图示关系进行介绍&#xff1a; Executor 该接口作为顶层接口只有一个execute()方法 execute(Runnable r) 该接口接受一个Runnable实例&#xff0c;即要执行的任务ExecutorService 该…

Executors工具类的相关方法

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生。本篇将记录创建线程池的Executors工具类里面的方法&#xff0c;方便加深知识印象和复习使用。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&#xff0c;也适合复习中&#xff0c;面试中的大佬&a…

java并发编程:Executor、Executors、ExecutorService

Executors 在Java 5之后&#xff0c;并发编程引入了一堆新的启动、调度和管理线程的API。Executor框架便是Java 5中引入的&#xff0c;其内部使用了线程池机制&#xff0c;它在java.util.cocurrent 包下&#xff0c;通过该框架来控制线程的启动、执行和关闭&#xff0c;可以简化…

nlinfit非线性回归拟合

% % 使用指定函数对下述两变量进行曲线拟合 % % yak1*exp(m*t)k2*exp(-m*t); % % 离散点: t[0,4,8,40], % % y[20.09,64.52,85.83,126.75]; % % t-自变量 y-因变量 a,m,k1,k2为常数 % % 用非线性回归nlinfit&#xff0c;如果数据点多些&#xff0c;效果会更好。 脚本&…

matlab的nlinfit函数,用matlab如何进行非线性拟合 nlinfit函数?

用非线性回归nlinfit&#xff0c;如果数据点多些&#xff0c;效果会更好。 function nonlinefit clc;clear; t[0 4 8 40]; y[20.09 64.52 85.83 126.75]; betanlinfit(t,y,myfunc,[1 1 1 1]) abeta(1) k1beta(2) k2beta(3) mbeta(4) tt0:1:40 yyak1*exp(m*tt)k2*exp(-m*tt) plo…

【MATLAB统计分析与应用100例】案例013:matlab读取Excel数据,调用nlinfit函数作一元非线性回归

1. 一元线性回归分析效果预览 2. matlab完整实现代码 %读取数据,绘制散点图** HeadData = xlsread(examp08_02.xls); %从Excel文

matlab中用polyfit、regress、nlinfit等进行详细的回归分析

目录 1.说明2.回归的介绍2-1.前面两篇所发现的一些问题2-1-1.回归和拟合是什么关系?2-1-2.回归到底是做预测还是用来去脏数据?3.三个函数的核心:最小二乘法3-1.介绍3-2.matlab代码4.函数polyfit(线性)5.函数regress(线性)5-1.输出b,bint,r,rint,stats5-2.应用5.2-1.一元…

曲线拟和函数lsqcurvefit nlinfit

转载自&#xff1a;http://panda0411.com/2011/08/29/curve-fit-and-function-lsqcurvefitnlinfit/ 琢磨了好久matlab自带的曲线拟和工具箱, 发现这货只能解决从离散数据得到各种类型的拟和效果, 但是反之貌似没法实现, google一下有这两个函数可以用:lsqcurvefit和nlinfit ls…

Matlab学习手记——非线性数据拟合:nlinfit和lsqcurvefit

目的&#xff1a;通过一个实例了解Matlab的数据拟合函数nlinfit和lsqcurvefit的使用。 结果图 具体数值 p 0.3000 50.0000 0.4000 200.0000 0.3000 800.0000 p1 0.3267 48.3589 0.4030 226.6525 0.2838 809.6680 p2 0.3267 48.3646 0.4031 226.735…

MATLAB多元非线性回归nlinfit拟合圆拟合球拟合函数

先上实验效果&#xff0c;你觉得有帮助可以继续阅读。代码解析在B站有上传视频&#xff08;用户昵称同名&#xff09;&#xff0c;代码也有详细备注。 拟合圆和球面&#xff1a; 拟合多元非线性函数&#xff1a;y p1*x1p2*x1^2p3*x2p4*x2^2exp(-p5*x3)的拟合结果&#xff1a;…

MATLAB 非线性隐函数拟合采坑记录(使用 fsolve solve nlinfit lsqcurvefit函数)

MATLAB 非线性隐函数拟合采坑记录&#xff08;使用 fsolve solve nlinfit lsqcurvefit函数&#xff09; 问题描述解决思路错误示范1代码思路原因解释模型更正更正模型1更正模型2 错误示范2代码思路原因解释模型更正更正模型1更正模型2 总结 问题描述 MATLAB的 nlinfit 和 lsqc…

Matlab多元非线性函数拟合

看了多篇文章&#xff0c;觉得没有一篇比较全&#xff0c;且可以参照的多元非线性函数拟合&#xff0c;看了多篇文章后总结以下内容&#xff0c;主要以示例给出&#xff0c;希望能帮助到大家快速上手。 1.需要用到的函数语法 beta nlinfit(X, Y, modelfun, beta0) X为你的自…

MATLAB中用nlinfit做多元非线性拟合(回归)

MATLAB中有一个多元非线性拟合的功能是nlinfit 基本语法是&#xff1a; beta nlinfit(X,Y,modelfun,beta0) 式子左边的beta可以是一个向量&#xff0c;向量的元素就是要回归的模型中的参数。 式子右边&#xff0c;modelfun是要回归的函数形式。X是函数的自变量数据&#xff1b…

使用nlinfit函数进行拟合时出现Error using nlinfit>checkFunVals (line 611)

在使用nlinfit函数进行拟合时出错&#xff0c;内容如下&#xff1a; The function you provided as the MODELFUN input has returned Inf or NaN values.从第一行可以看出&#xff0c;由于赋予的初始值导致了函数生成了NaN&#xff08;无解&#xff09;&#xff0c;所以整个回…