ExecutorService

接口 java.util.concurrent.ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行。在下面的例子中可以发现线程被循环创建,但是启动线程却不是连续的,而是由ExecutorService决定的。
ExecutorService是一个接口,继承了Executor。而Executor亦是一个接口,该接口只包含了一个方法:void execute(Runnable command);,该方法接收一个 Runable 实例,它用来执行一个任务,任务即一个实现了 Runnable 接口的类。

创建ExecutorService:
Executors 提供了一系列工厂方法用于创先线程池,返回的线程池都实现了 ExecutorService 接口。

  • public static ExecutorService newFixedThreadPool(int nThreads)
    创建固定数目线程的线程池。
  • public static ExecutorService newCachedThreadPool()
    创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线 程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
  • public static ExecutorService newSingleThreadExecutor()
    创建一个单线程化的Executor。
  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    创建一个支持延迟及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

ExecutorService 使用方法:
这里有几种不同的方式让你将任务委托给壹個 ExecutorService。

  • execute(Runnable)

      executorService.execute(new Runnable() {  
          public void run() {  
              System.out.println("Asynchronous task");  
          }  
      });  
    
  • Future submit(Runnable)
    同样接收壹個 Runnable 的实现作为参数,但是会返回一個 Future 对象。这個 Future 对象可以用于判断 Runnable 是否结束执行。
    Future future = executorService.submit(new Runnable() {
    public void run() {
    System.out.println("Asynchronous task");
    }
    });
    //如果任务结束执行则返回 null
    System.out.println("future.get()=" + future.get());

  • Future submit(Callable)
    Callable 的 call() 方法可以返回壹個结果。Callable 的返回值可以从方法 submit(Callable) 返回的 Future 对象中获取。
    Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
    System.out.println("Asynchronous Callable");
    return "Callable Result";
    }
    });
    System.out.println("future.get() = " + future.get());

  • T invokeAny(Collection)
    任务集合中,任何一个任务完成就返回。
    接收Callable 对象的集合作为参数。调用该方法不会返回 Future 对象,而是返回集合中某一個 Callable 对象的结果。
    无法保证调用之后返回的结果是哪個 Callable。
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Set> callables = new HashSet>();
    callables.add(new Callable() {
    public String call() throws Exception {
    return "Task 1";
    }
    });
    callables.add(new Callable() {
    public String call() throws Exception {
    return "Task 2";
    }
    });
    callables.add(new Callable() {
    public String call() throws Exception {
    return "Task 3";
    }
    });
    String result = executorService.invokeAny(callables);
    System.out.println("result = " + result);
    executorService.shutdown();

  • List invokeAll(Collection)
    同步的方法,执行所有的任务列表,当所有任务都执行完成后,返回Future列表。

执行 Runnable 任务:
通过 Executors 的以上四个静态工厂方法获得 ExecutorService 实例,而后调用该实例的 execute(Runnable command)方法即可。一旦 Runnable 任务传递到 execute()方法,该方法便会自动在一个线程上执行。下面是 Executor 执行 Runnable 任务的示例代码:

import java.util.concurrent.ExecutorService;   
import java.util.concurrent.Executors;   

public class TestCachedThreadPool{   
    public static void main(String[] args){   
        ExecutorService executorService = Executors.newCachedThreadPool();   
//      ExecutorService executorService = Executors.newFixedThreadPool(5);  
//      ExecutorService executorService = Executors.newSingleThreadExecutor();  
        for (int i = 0; i < 5; i++){   
            executorService.execute(new TestRunnable());   
            System.out.println("************* a" + i + " *************");   
        }   
        executorService.shutdown();   
    }   
}   

class TestRunnable implements Runnable{   
    public void run(){   
        System.out.println(Thread.currentThread().getName() + "线程被调用了。");   
    }   
}

执行结果如下:

ExecutorService_第1张图片

从结果中可以看出,pool-1-thread-1 和 pool-1-thread-2 均被调用了两次,这是随机的,execute 会首先在线程池中选择一个已有空闲线程来执行任务,如果线程池中没有空闲线程,它便会创建一个新的线程来执行任务。

ExecuteService 服务的关闭:
当使用 ExecutorService 完毕之后,我们应该关闭它。 例如:你的程序通过 main() 方法启动,并且主线程退出了你的程序,如果你还有壹個活动的 ExecutorService 存在于你的程序中,那么程序将会继续保持运行状态。存在于 ExecutorService 中的活动线程会阻止Java虚拟机关闭。
为了关闭在 ExecutorService 中的线程,你需要调用 ***shutdown() 方法。executorService.shutdown();ExecutorService 并不会马上关闭,而是不再接收新的任务,壹但所有的线程结束执行当前任务,ExecutorServie 才会真的关闭。所有在调用 shutdown() 方法之前提交到 ExecutorService 的任务都会执行。
如果你希望立即关闭 ExecutorService,你可以调用
shutdownNow() ***方法。executorService.shutdownNow();这個方法会尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。但是对于正在执行的任务,是否能够成功关闭它是无法保证的。
awaitTermination方法,方法调用会被阻塞,直到所有任务执行完毕并且shutdown请求被调用,或者参数中定义的timeout时间到达,或者当前线程被打断,这几种情况任意一个发生了就会导致该方法的执行。接收timeout和TimeUnit两个参数,用于设定超时时间及单位。当等待超过设定时间时,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。(若超时未关闭,程序也继续往下进行。传入Long.MAX_VALUE, TimeUnit.DAYS参数,可确保子进程完成。)一般情况下会和shutdown方法组合使用。

// 关闭启动线程 
service.shutdown(); 
// 等待子线程结束,再继续执行下面的代码 
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);  //这里表示近似永远等待
//service.awaitTermination(1, TimeUnit.MINUTES);//等待一分钟
//service.awaitTermination(2, TimeUnit.SECONDS);//两秒钟
System.out.println("all thread complete");

还有 service.isTerminated()service.isTerminating()service.isShutdown()等方法。


参考:
http://wiki.jikexueyuan.com/project/java-concurrency/executor.html
http://blog.csdn.net/bairrfhoinn/article/details/16848785
http://shift-alt-ctrl.iteye.com/blog/1841088

你可能感兴趣的:(ExecutorService)