Java多线程之Executor、ExecutorService、Executors、Callable、Future与FutureTask
1. 引子
初学Java多线程,常使用Thread与Runnable创建、启动线程。如下例:
Thread t1 = new Thread(newRunnable() {
@Overridepublic voidrun() {
System.out.println(Thread.currentThread().getName());
}
});
t1.start();
我们需要自己创建、启动Thread对象。
重要概念:
实现Runnable的类应该被看作一项任务,而不是一个线程。在Java多线程中我们一定要有一个明确的理解,任务和线程是不同的概念。可以使用线程(Thread)执行任务(比如Runnable),但任务不是线程。
Java多线程中有两种不同类型的任务,Runnable类型任务(无返回值)与Callable类型任务(有返回值)。
2. 使用Executor执行线程
一些已有的执行器可以帮我们管理Thread对象。你无需自己创建与控制Thread对象。比如,你不用在代码中编写new Thread或者thread1.start()也一样可以使用多线程。如下例:
ExecutorService exec =Executors.newCachedThreadPool();for (int i = 0; i < 5; i++) {//5个任务
exec.submit(newRunnable() {
@Overridepublic voidrun() {
System.out.println(Thread.currentThread().getName()+"doing task");
}
});
}
exec.shutdown();//关闭线程池
输出如下:
pool-1-thread-2doing task
pool-1-thread-1doing task
pool-1-thread-3doing task
pool-1-thread-4doing task
pool-1-thread-5 doing task
从输出我们可以看到,exec使用了线程池1中的5个线程做了这几个任务。
这个例子中exec这个Executor负责管理任务,所谓的任务在这里就是实现了Runnable接口的匿名内部类。至于要使用几个线程,什么时候启动这些线程,是用线程池还是用单个线程来完成这些任务,我们无需操心。完全由exec这个执行器来负责。在这里exec(newCachedThreadPool)指向是一个可以根据需求创建新线程的线程池。
Executors相当于执行器的工厂类,包含各种常用执行器的工厂方法,可以直接创建常用的执行器。几种常用的执行器如下:
Executors.newCachedThreadPool,根据需要可以创建新线程的线程池。线程池中曾经创建的线程&#