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则是为了让任务更加快速的执行完毕。

【Java基础】ExecutorService的使用的更多相关文章

  1. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  2. 【java基础之jdk源码】Object

    最新在整体回归下java基础薄弱环节,以下为自己整理笔记,若有理解错误,请批评指正,谢谢. java.lang.Object为java所有类的基类,所以一般的类都可用重写或直接使用Object下方法, ...

  3. JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

    JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...

  4. java基础常见面试题,这是一篇超长的随笔!!!

    1. Java基础部分....................................................... 4 1.一个".java"源文件中是否可以包括 ...

  5. Java基础-进程与线程之Thread类详解

    Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...

  6. 笔试题之java基础

    Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他.有些题来自网上搜集整理,有些题来自传智 ...

  7. 40道Java基础常见面试题及详细答案

    最近看到网上流传着各种面试经验及面试题,往往都是一大堆技术题目贴上去,但是没有答案. 为此我业余时间整理了40道Java基础常见的面试题及详细答案,望各路大牛发现不对的地方不吝赐教,留言即可. 八种基 ...

  8. Java基础16:Java多线程基础最全总结

    Java基础16:Java多线程基础最全总结 Java中的线程 Java之父对线程的定义是: 线程是一个独立执行的调用序列,同一个进程的线程在同一时刻共享一些系统资源(比如文件句柄等)也能访问同一个进 ...

  9. Java 基础总结

    Java基础总结 jdk:Java的开发环境与部署环境jre:Java的运行环境 Java数据类型分为:基本类型和引用类型 基本类型:①整数类型 byte   short   int   long 默 ...

  10. 一份最贴近真实面试的Java基础面试题

    这是一份Java基础知识的面试题.在网上的关于Java的面试题数不胜数,但认真看过感觉大多数都没有实用性,有很多是面试官根本就不会问到的,那些已经脱离了实际开发的技术问题.而这份资料来源自一份个人觉得 ...

随机推荐

  1. redis 内存划分

    1.数据:作为数据库,数据是最主要的部分,这部分占用的内存会被统计在used_memory中 2.进程内存:redis主进程本身运行需要占用的内存,这部分内存会被统计在used_memory_rss中 ...

  2. [python]Appium+python +pytest 实现APP自动化,基于安卓

    1.安卓环境搭建 &关于app自动化,个人觉得安装过程比较复杂,脚本难度实现和web自动化差不多封装关键字即可,因此,下面会写安装.启动APP以及过程中遇到的一些坑(这一篇偏向解释给个人) & ...

  3. Java 源码如何分析?

    如何阅读源码?万事开头难,源码从哪里开始看?我也是刚对源码的阅读研究不深,但是可以谈谈自己的源码阅读感受. 刚开始吧,只是对某些代码的实现原理感到好奇,好奇是怎么实现这种功能,实现这种效果的,对其背后 ...

  4. macos command 'clang' failed with exit status 1

    export CC=$(which gcc)export CXX=$(which g++)pip install fbprophet CC=clang pip install gevent

  5. SpringBoot 整合 Mybatis-Plus + Mysql

    mybatis-plus是mybatis的一款插件,它的主要作用是快速开发,省略mybatis的配置,具体的功能请参照官网. 开发环境: springboot,maven,mybatis-plus,m ...

  6. XMLHttpRequest—>Promise

    XMLHttpRequest.open() 初始化 HTTP 请求参数 语法open(method, url, async, username, password) method 参数是用于请求的 H ...

  7. 一个简单的golang项目,实验 gitlab-ci-cd Pipelines

    至少两台主机,gitlab + gitlab-runner gitlab + gitlab-runner安装略 项目源码:https://gitee.com/M27149/testgo.git 在自建 ...

  8. [loj2469]最小方差生成树

    2018年论文题 约定:令点集$V=[1,n]$.边集$E=[1,m]$,记$m$条边依次为$e_{i}=(x_{i},y_{i},c_{i})$(其中$1\le i\le m$),将其按照$c_{i ...

  9. idea文件多行显示

    将红色部分取消勾选

  10. Ubuntu 18.04 WMware 编译 AOSP android-7.1.2_r33 笔记

    0 前言 问:都快2022年了,为什么还要编译 android 7.1.2 ? 答:某脱壳机特征修改或移植到其他机型(此处省略1000字...) 笔者在编译之前并没有加入专有二进制文件(后续加入了再补 ...