Executor 是jdk并发编程顶层接口,定义了线程池的标准。
它包含了一个方法execute,参数为一个Runnable接口引用。
源码:
public interface Executor {
void execute(Runnable command);
}
原文:
An object that executes submitted Runnable tasks. 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. An Executor is normally used instead of explicitly creating
threads. For example, rather than invoking new
Thread(new(RunnableTask())).start() for each of a set of tasks, you
might use:
该接口实现类会执行 Runnable 任务,它提供了一种方式将任务的提交与怎样运行(例如使用线程细节,定时任务等等)解耦分离, 使用 Executor 的话,我们不需要显示的创建一堆线程并通过
new Thread(new (RunnableTask())).start()
来执行,你可以这样做
代码1
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
原文:
However, the Executor interface does not strictly require that
execution be asynchronous. In the simplest case, an executor can run
the submitted task immediately in the caller’s thread
而Executor 没有要求这些任务的执行一定异步的,举个最简单的例子,一个而Executor可以立刻来执行提交的Runnable任务。
代码2
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. The executor below serializes the
submission of tasks to a second executor, illustrating a composite
executor.
许多Executor的实现类利用了特殊的处理来制定任务何时执行和怎样执行。下面的executor使得tasks 顺序的一进一出的执行,代码描述如下:
代码3
class SerialExecutor implements Executor {
final Queue tasks = new ArrayDeque();
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);
}
}
}}
ArrayDeque是一个特殊的双端队列,这里仅当先进先出的普通队列理解就好了。execute方法负责任将任务塞入队列,scheduleNext方法负责将人物从队列中取出来 执行executor.execute(active) 方法处理。
原文
The Executor implementations provided in this package implement
ExecutorService, which is a more extensive interface. The
ThreadPoolExecutor class provides an extensible thread pool
implementation. The Executors class provides convenient factory
methods for these Executors.
jdk并发包中提供的Executor的实现类实现的是Executor的扩展接口ExecutorService,ThreadPoolExecutor就是最常见的实现类,它是一个可扩展的线程池的实现。而 Executors 提供了实例化这些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.
存一致性影响:提交给ExecutorService中同的一个线程中的任务满足happen-before(偏序关系),就是说如果一个线程先提交,那么它也应该先执行。
总结:想理解多线程必须深入了解线程池的实现原理。
个人认为需要理解以下几点:
Thread 和 Runnalbe的区别要弄清楚,Runnalbe仅仅作为 Thread 的构造方法参数而已。
例如:
public class MyTask implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
}
Thread thread = new Thread(new MyTask());
如果 thread.start() 会开启新的线程,并且内部就是执行的是MyTask的run()方法。
而thread.run()不会开启新的线程。
从这里可以看出来,MyTask就是Runnable
类型任务,是Thread的构造方法的参数,仅此而已,线程池的核心就是用有限的Thread来执行多个Runnable
类型任务。
下面的几点就是上面描述的几个例子要说明的内容
表明了Executor用来执行Runnable 类型的任务,可以同步来执行或者异步来执行。参考 代码1
表明了Executor内部可以生成线程来执行Runnable任务。参考 代码2
最后一个例子线程池运行的核心机制,维护一个队列,一头提交任务到队列, 另一头取出任务来执行。参考 代码3
这3点就是jdk线程池的核心部分的原理了(如果再看一本文理解会更好),之后讲解其他线程池相关的类,都是围绕这个体系的。