本文是对Java并发包中Executor接口的翻译介绍, 通过该文, 笔者一方面练习英文, 一方面目的理解JDK源码, 所以根据自己的理解, 可能不是直译, 并且添加一些自己的笔记.
由于是为了自己学习做笔记用, 简单的句子直接跳过不翻译.
An object that executes submitted Runnable tasks.
Executor是用于提交Runnable task的类.
This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc.
该接口提供了一种将任务提交与每个任务的运行机制分离的方法,包括线程使用、调度等细节。
-- 以前创建线程, 只能通过继承Thread或者实现Runnable接口两种方式, 定义和运行是集中在一起的, 现在Executor提供了一种, 将定义和运行分离的新方式.
An Executor is normally used instead of explicitly creating threads.
扫描二维码关注公众号,回复: 13291529 查看本文章![]()
Executor通常用来替代显式的创建线程.
-- 意思就是, 不在显式的创建线程了.
For example, rather than invoking new Thread(new(RunnableTask())).start() for each of a set of tasks, you might use:
使用一种直接执行的方式, 而不是new Thread(RunnableTask())).start(), 下面是使用案例
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...
However, the Executor interface does not strictly require that execution be asynchronous.
Executor接口并不严格要求执行的任务是异步的.
-- 意思是, 并非只有异步的任务才可以使用Executor, 如果你愿意弄一个直接运行的任务, 也无所谓. 例如下面大师就开始举了个栗子
In the simplest case, an executor can run the submitted task immediately in the caller's thread:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
在上面的简单例子中, executor直接在caller线程中运行了任务
More typically, tasks are executed in some thread other than the caller's thread.
The executor below spawns a new thread for each task.
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}
更加经典典型的用法是, 重新创建一个新线程, 去执行提交过来的任务
Many Executor implementations impose some sort of limitation on how and when tasks are scheduled.
Executor的实现类, 在如何运行调度任务上添加了自己的限制.
The executor below serializes the submission of tasks to a second executor, illustrating a composite executor.
下面的executor, 在执行完提交的Runnable之后, 接着执行了Queue tasks里面的任务, 形成了一个复合的executor
-- 下面的代码中, 就在finally中, 执行完队列中的Runnable任务
-- 意思就是, 通过举例说明, Executor的实现是个性化的, 这个例子就是一个连续任务的Executor.
class SerialExecutor implements Executor {
final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
final Executor executor;
Runnable active;
SerialExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (active == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}
The Executor implementations provided in this package implement ExecutorService, which is a more extensive interface.
在当前包中的Executor的实现类多是实现自ExecutorService, ExecutorService一个更加被广泛使用的接口
The ThreadPoolExecutor class provides an extensible thread pool implementation.
ThreadPoolExecutor是一个被广泛使用的线程池,
The Executors class provides convenient factory methods for these Executors.
Executors(注意加了s, 不同与本文的Executor接口)为这些Executor们提供了方面的工厂方法
Memory consistency effects: Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.
下面是关于Executor的使用Demo
/**
* 功能说明:初识Executor
* 运行结果如下;
*
* hello executor1
* MyExecutor1 当前线程名称: main
* hello executor2
* MyExecutor2 当前线程名称: Thread_new
*
*
* 思考问题: 为什么大师要在已经有了创建和运行线程的方式下,重复早轮子, 提供一个Executor呢?
* 回答: 之前的创建线程的方式
* 1, 继承Thread
* 2, 实现Runnable接口
* 这两种方式,定义任务和运行是集中在一起的, Executor只负责运行.
* 开发人员:@author MaLi
*/
public class MT20_Executor {
public static void main(String[] args) {
//方式1, 直接运行, 也就是在caller线程中提交到Executor
new MyExecutor1().execute(()-> System.out.println("hello executor1"));
// 方式2, 异步运行
new MyExecutor2().execute(()-> System.out.println("hello executor2"));
}
static class MyExecutor1 implements Executor{
@Override
public void execute(Runnable command) {
//直接运行的方式
command.run();
System.out.println("MyExecutor1 当前线程名称: "+ Thread.currentThread().getName());
}
}
static class MyExecutor2 implements Executor{
@Override
public void execute(Runnable command) {
//异步的方式运行提交的新线程
new Thread(()->{
command.run();
System.out.println("MyExecutor2 当前线程名称: "+ Thread.currentThread().getName());
},"Thread_new").start();
}
}
}