java并发中ExecutorService的具体用法

 更新时间:2025年09月02日 11:15:47   作者:flydean程序那些事  
本文深入探讨Java中的ExecutorService框架,介绍其创建方法、任务分配、关闭策略及Future、ScheduledExecutorService的使用,对比Fork/Join框架,提供丰富的代码示例,感兴趣的朋友跟随小编一起看看吧

ExecutorService是java中的一个异步执行的框架,通过使用ExecutorService可以方便的创建多线程执行环境。

本文将会详细的讲解ExecutorService的具体使用。

创建ExecutorService

通常来说有两种方法来创建ExecutorService。

第一种方式是使用Executors中的工厂类方法,例如:

ExecutorService executor = Executors.newFixedThreadPool(10);

除了newFixedThreadPool方法之外,Executors还包含了很多创建ExecutorService的方法。

第二种方法是直接创建一个ExecutorService, 因为ExecutorService是一个interface,我们需要实例化ExecutorService的一个实现。

这里我们使用ThreadPoolExecutor来举例:

ExecutorService executorService =
            new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>());

为ExecutorService分配Tasks

ExecutorService可以执行Runnable和Callable的task。其中Runnable是没有返回值的,而Callable是有返回值的。我们分别看一下两种情况的使用:

Runnable runnableTask = () -> {
    try {
        TimeUnit.MILLISECONDS.sleep(300);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};
Callable<String> callableTask = () -> {
    TimeUnit.MILLISECONDS.sleep(300);
    return "Task's execution";
};

将task分配给ExecutorService,可以通过调用xecute(), submit(), invokeAny(), invokeAll()这几个方法来实现。

execute() 返回值是void,他用来提交一个Runnable task。

executorService.execute(runnableTask);

submit() 返回值是Future,它可以提交Runnable task, 也可以提交Callable task。 提交Runnable的有两个方法:

<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

第一个方法在返回传入的result。第二个方法返回null。

再看一下callable的使用:

Future<String> future = 
  executorService.submit(callableTask);

invokeAny() 将一个task列表传递给executorService,并返回其中的一个成功返回的结果。

String result = executorService.invokeAny(callableTasks);

invokeAll() 将一个task列表传递给executorService,并返回所有成功执行的结果:

List<Future<String>> futures = executorService.invokeAll(callableTasks);

关闭ExecutorService

如果ExecutorService中的任务运行完毕之后,ExecutorService不会自动关闭。它会等待接收新的任务。如果需要关闭ExecutorService, 我们需要调用shutdown() 或者 shutdownNow() 方法。

shutdown() 会立即销毁ExecutorService,它会让ExecutorServic停止接收新的任务,并等待现有任务全部执行完毕再销毁。

executorService.shutdown();

shutdownNow()并不保证所有的任务都被执行完毕,它会返回一个未执行任务的列表:

List<Runnable> notExecutedTasks = executorService.shutdownNow();

oracle推荐的最佳关闭方法是和awaitTermination一起使用:

executorService.shutdown();
       try {
           if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
               executorService.shutdownNow();
           }
       } catch (InterruptedException e) {
           executorService.shutdownNow();
       }

先停止接收任务,然后再等待一定的时间让所有的任务都执行完毕,如果超过了给定的时间,则立刻结束任务。

Future

submit() 和 invokeAll() 都会返回Future对象。之前的文章我们已经详细讲过了Future。 这里就只列举一下怎么使用:

Future<String> future = executorService.submit(callableTask);
String result = null;
try {
   result = future.get();
} catch (InterruptedException | ExecutionException e) {
   e.printStackTrace();
}

ScheduledExecutorService

ScheduledExecutorService为我们提供了定时执行任务的机制。

我们这样创建ScheduledExecutorService:

ScheduledExecutorService executorService
                = Executors.newSingleThreadScheduledExecutor();

executorService的schedule方法,可以传入Runnable也可以传入Callable:

Future<String> future = executorService.schedule(() -> {
        // ...
        return "Hello world";
    }, 1, TimeUnit.SECONDS);
    ScheduledFuture<?> scheduledFuture = executorService.schedule(() -> {
        // ...
    }, 1, TimeUnit.SECONDS);

还有两个比较相近的方法:

scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit )
scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit ) 

两者的区别是前者的period是以任务开始时间来计算的,后者是以任务结束时间来计算。

ExecutorService和 Fork/Join

java 7 引入了Fork/Join框架。 那么两者的区别是什么呢?

ExecutorService可以由用户来自己控制生成的线程,提供了对线程更加细粒度的控制。而Fork/Join则是为了让任务更加快速的执行完毕。

本文的代码请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorService

到此这篇关于java并发中ExecutorService的具体用法的文章就介绍到这了,更多相关java ExecutorService使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java使用xpath解析xml示例分享

    java使用xpath解析xml示例分享

    XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力,下面是一小示例,需要的朋友可以参考下
    2014-03-03
  • Spring框架原理之实例化bean和@Autowired实现原理方式

    Spring框架原理之实例化bean和@Autowired实现原理方式

    这篇文章主要介绍了Spring框架原理之实例化bean和@Autowired实现原理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • Java contains用法示例

    Java contains用法示例

    这篇文章主要介绍了Java contains的用法示例,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-11-11
  • JAVA操作HDFS案例的简单实现

    JAVA操作HDFS案例的简单实现

    本篇文章主要介绍了JAVA操作HDFS案例的简单实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java中的Reference和引用类型实例精讲

    java中的Reference和引用类型实例精讲

    这篇文章主要为大家介绍了java中的Reference和引用类型示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Java隐藏特性之双括号初始化详解

    Java隐藏特性之双括号初始化详解

    Java 语言拥有许多隐藏而强大的特性,其中之一是双括号初始化,这篇文章将详细介绍双括号初始化的概念、用法和示例代码,希望对大家有所帮助
    2023-12-12
  • java中ThreadPoolExecutor常识汇总

    java中ThreadPoolExecutor常识汇总

    这篇文章主要介绍了java中ThreadPoolExecutor常识汇总,线程池技术在并发时经常会使用到,java中的线程池的使用是通过调用ThreadPoolExecutor来实现的,需要的朋友可以参考下
    2019-06-06
  • Java+Selenium调用JavaScript的方法详解

    Java+Selenium调用JavaScript的方法详解

    这篇文章主要为大家讲解了java在利用Selenium操作浏览器网站时候,有时会需要用的JavaScript的地方,代码该如何实现呢?快跟随小编一起学习一下吧
    2023-01-01
  • SpringBoot静态资源与首页配置实现原理深入分析

    SpringBoot静态资源与首页配置实现原理深入分析

    最近在做SpringBoot项目的时候遇到了“白页”问题,通过查资料对SpringBoot访问静态资源做了总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • Apache SkyWalking 监控 MySQL Server 实战解析

    Apache SkyWalking 监控 MySQL Server 实战解析

    这篇文章主要介绍了Apache SkyWalking 监控 MySQL Server 实战解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09

最新评论