Executor框架

 这篇文章主要来讲解jdk1.5开始引进的Executor框架。

 先看一下Executor接口的源码:

public interface Executor {
    void execute(Runnable command);
}

 该接口只声明了一个方法execute,该方法的参数是Runnable类型,结合这个声明和Runnable的特性我们可以大概明白这个方法要实现的内容是用一个线程去完成command要完成的任务。

 ExecutorService接口扩展了Executor接口。

public interface ExecutorService extends Executor {
    void shutdown();
    List<Runnable> shutdownNow();
    boolean isShutdown();
    boolean isTerminated();
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

 接口声明的方法有isShutdown()和isTerminated()来判断ExecutorService的状态,加上运行时的状态,可以想到ExecutorService有三种状态:运行、关闭和已终止。ExecutorService在初创建时处于运行状态。shutdown()方法将执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成(包括那些还未开始执行的任务)。shutdownNow()将粗暴地关闭:它将尝试取消所有运行中的任务,并且不再启动队列中为开始执行的任务。shutdownNow()方法将返回还未执行的任务。

 submit()方法提交要执行的任务并返回一个Future对象,可以获取任务执行的结果或获取任务执行时出现的异常。

 

线程池

 在jdk1.8里,Executors可以创建的线程池有一下几种:

newFixedThreadPool 该线程池将创建一个固定长度的线程池,每当提交一个任务时就创建一个线程,知道达到线程池的最大数量,线程池里线程的数量将不再变化。如果某个线程由于发生了未预期的Exception而结束,那么线程池会补充一个新的线程。

newCachedThreadPool 该线程池的规模不存在任何限制,如果线程多于处理需求,将回收空余线程,如果线程少于处理需求,将添加新的线程。

newSingleThreadExecutor 该线程池只有一个线程,如果这个线程异常结束,会创建另一个线程来替代。

newScheduledThreadPool 该线程池创建固定数量的线程,而且以延迟或定时的方式来执行任务。

newWorkStealingPool 这个是jdl1.8加入的线程池方法,创建一个以可用处理器的数量作为目标并行度的线程池。

上面的线程池方法返回的线程池都是实现了ExecutorService接口的。每种线程池的使用方法都大致相同,但是各种线程池之间执行的结果可能是有很大差别的。

public static void main(String [] args){
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                for (int i = 0; i < 1000; i++){
                    System.out.println(i);
                }
                return 1;
            }
        };
        executor.submit(callable);
        executor.submit(callable);
        executor.submit(callable);
        executor.submit(callable);
        executor.submit(callable);
        System.out.println(executor.submit(callable));
        executor.shutdown();
}

 这个例子在newSingleThreadExecutor线程池和newCachedThreadPool就很可能有不同的结果。

 

posted @ 2018-03-27 19:05  Gouden  阅读(80)  评论(0)    收藏  举报