java.util.concurrent.Executor

原创
2014/06/19 21:32
阅读数 696

首先是concurrent里面最简单也是最基础的一个接口 Executor, 先在这里卖个关子,为什么这个接口只有一个方法。为什么ExecutorService(点击查看源码分析),会去继承这个接口,而不是直接把这个方法纳入到自己的实现中?

上源代码:

package java.util.concurrent;

public interface Executor {

    void execute(Runnable command);
}

  • 参数:Runnable 这个不用介绍了吧

  • 返回:无

  • 异常:

    • RejectedExecutionException - 如果这个任务不可以被执行

    • NullPointException - 臭名昭著的空指针异常,当command为空的时候


我们都知道如何使用Runnable来实现一个新的线程

Thread thread = new Thread(new Runnable(){
    @Override
    public void run(){
        //your code
    }
});
thread.start();


从源码的注释中可以看出,这个接口可以这样实现:

class DirectExecutor implements Executor {
    public void execute(Runnable r) {
        r.run(); //直接调用run方法,将会在当前线程中执行任务。
    }
}

或者是异步的多线程实现

class ThreadPerTaskExecutor implements Executor {
    public void execute(Runnable r) {
        new Thread(r).start(); //新建一个线程来执行这个任务
    }
}

更复杂一点严格的串行执行

/**
 *当第一个任务被加载时,会被执行,如果第一个没有执行完成的情况下
 *第二个任务被执行时,只会推入队列,而不会被执行,
 *只有当第一个被执行完成的时候才会触发第二个任务的执行。
 */
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);
        }
    }
}


从Executor的命名就可以知道,作者并非强调多线程而在于执行。从上面三个例子,大家可以体会到这个执行的具体含义了吧。

展开阅读全文
加载中
点击加入讨论🔥(1) 发布并加入讨论🔥
打赏
1 评论
2 收藏
2
分享
返回顶部
顶部