java并发中ExecutorService的使用

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

更多教程请参考 flydean的博客

java并发中ExecutorService的使用的更多相关文章

  1. java并发中的Synchronized关键词

    文章目录 为什么要同步 Synchronized关键词 Synchronized Instance Methods Synchronized Static Methods Synchronized B ...

  2. 深入浅出Java并发中的CountDownLatch

      1. CountDownLatch 正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.在Java并发中 ...

  3. java并发中CountDownLatch的使用

    文章目录 主线程等待子线程全都结束之后再开始运行 等待所有线程都准备好再一起执行 停止CountdownLatch的await java并发中CountDownLatch的使用 在java并发中,控制 ...

  4. Java 并发工具包——ExecutorService常用线程池

    1. 执行器服务 ExecutorService java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务.因此一个 Executo ...

  5. Java并发中的CopyOnWrite容器

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

  6. 一起来看看java并发中volatile关键字的神奇之处

    并发编程中的三个概念: 1.原子性 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. 2.可见性 对于可见性,Java提供了volati ...

  7. Volatile 原理及使用,java并发中的可见性问题

    1.解决并发编程中的可见性问题 volatile 代表不使用cpu缓存,修改后的数据,将直接刷到内存中,被volatile修饰的变量,读取的时候,也是从内存中读取,不从cpu缓存中读取 上代码 // ...

  8. java并发中的Semaphore

    什么是Semaphore Semaphore可以控制某个资源可被同时访问的个数(locks和synchronized锁,在任何时刻只允许一个任务访问一个资源),通过acquire()获取一个许可,如果 ...

  9. java concurrent 中ExecutorService和CompletionService简单区别

    举个例子,现在需要执行10个任务,这些任务都是有返回值,并且需要使用10个线程同时执行.一般的做法就是创建ExecutorService线程池,pool大小10,每个任务实现Callable接口,然后 ...

随机推荐

  1. Ruby学习计划-(0)前言

      前言   接触过的编程语言现在来说有C.C++.Java.Object-C.Swift.这几门语言中最熟悉的就是oc了,毕竟靠他吃饭,对于其他几门语言都是初入门径而已,由于本身一直从事iPhone ...

  2. WPF使用 Gmap.NET 绘制极坐标运动轨迹

    大家好,已经很久没有更新了,今天写一篇关于WPF 使用 Gmap.NET 相关的,网上很多Winform的很**,所以我给Wpf进行一些补充.虽然它已经很久没有更新了,但是也只能用这个了.没别的好选择 ...

  3. 《Java基础复习》-控制执行流程

    最近任务太多了,肝哭我了,boom 参考书目:Thinking in Java <Java基础复习>-控制执行流程 Java使用了C的所有流程控制语句 涉及关键字:if-else.whil ...

  4. python编程心得(1)

    1.创建字典     字典名 = {键名1:键值1,键名2:键值2,...}     sanguo = {"诸葛亮草船借箭":"满载而归","关公赴会 ...

  5. 1047 Student List for Course (25分)

    Zhejiang University has 40,000 students and provides 2,500 courses. Now given the registered course ...

  6. Java数组的声明与创建

    今天在刷Java题的时候,写惯了C++发现忘记了Java数组的操作,遂把以前写的文章发出来温习一下. 首先,数组有几种创建方式? Java程序中的数组必须先进行初始化才可以使用,所谓初始化,就是为数组 ...

  7. python 爬虫:学爬虫必学的正则表达式

    文章更新于:2020-03-30 一.语法格式 1.非打印字符 操作符 说明 实例 \cx 匹配由x指明的控制字符 \cM 匹配一个 Control-M 或回车符.x 的值必须为 A-Z 或 a-z ...

  8. MTK Android 设置-选择日期格式 [管理和组织首选项,ListPreference,CheckBoxPreference,EditTextPreference,RingtonePreference]

    ###android.preference.ListPreference的一些特性 android:key  选项的名称或键 android:title  选项的标题 android:summary  ...

  9. MTK Android Driver :Memory

    型号配置: 1.CUSTOM_MEMORY_HDR(需要确认是否是MTK认证的flash ic) mediatek\custom\$(PROJECT)\preloader\inc\custom_Mem ...

  10. javascript入门 之 ztree(二 标准json数据)

    1.代码 <!DOCTYPE html> <HTML> <HEAD> <TITLE> ZTREE DEMO - Standard Data </T ...