您的位置:首页 > 编程语言 > Java开发

Java多线程 之 执行器Executor(二)

2016-06-01 22:01 381 查看
java多线程很少像前面的例子那样直接使用Thread.start()方法来驱动。而是使用执行器Executor来管理线程。执行器是启动任务的最佳方法。

ExecutorService(一个具有服务生命周期的执行器)知道如何创建恰当的上下文来执行Runnable对象。请看下面的例子(其中LiftOff参见上一篇文章):

package org.fan.learn.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by thinkpad on 2016/6/1.
*/
public class ExecutorTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new LiftOff());
}
executorService.shutdown();
System.out.println("Waiting for liftOff!");
}
}


执行结果如下所示:

Waiting for liftOff!

Task(0)#9 Task(1)#9 Task(2)#9 Task(0)#8 Task(1)#8 Task(3)#9 Task(4)#9 Task(2)#8 Task(0)#7 Task(1)#7 Task(3)#8 Task(4)#8 Task(2)#7 Task(0)#6 Task(1)#6 Task(3)#7 Task(4)#7 Task(2)#6 Task(0)#5 Task(1)#5 Task(3)#6 Task(4)#6 Task(2)#5 Task(0)#4 Task(1)#4 Task(3)#5 Task(4)#5 Task(2)#4 Task(0)#3 Task(1)#3 Task(3)#4 Task(4)#4 Task(2)#3 Task(0)#2 Task(1)#2 Task(3)#3 Task(4)#3 Task(2)#2 Task(0)#1 Task(1)#1 Task(3)#2 Task(4)#2 Task(2)#1 Task(0)#liftOff Task(1)#liftOff Task(3)#1 Task(4)#1 Task(2)#liftOff Task(3)#liftOff Task(4)#liftOff

注意,上面对shutdown方法的调用:

调用shutdown方法可以防止新任务被提交到这个执行器,当前线程(即驱动main的线程,其实这个线程是由操作系统创建的。例如在linux的shell中执行一个命令,其实是由shell fork出了一个进程来执行的)会继续运行在shutdown被调用之前提交的所有任务。这个当前线程将在执行器中的所有任务完成之后退出。

CachedThreadPool将在线程执行过程中创建与所需数量相同的线程,而且在它开始对旧线程回收时将停止创建新的线程。CachedThreadPool每当用到新线程时就创建一个线程,而创建线程的开销是很大的,但是在Thinking in Java中,却说CachedThreadPool是合理的执行器的首选。

除了CachedThreadPool之外还有FixedThreadPool。可以给Executors.newFixedThreadPool传递一个参数,表示线程池中线程的是数量。这样,程序在执行过程中就可以直接使用线程池中的线程,而不用花费很大在线程创建上。但是也有一个弊端就是,线程数量已经固定,无法按照需要再创建新的线程。

在Thinking in java中有这么一句话:在任何线程池中,现有线程在可能的情况下,都会被自动复用。也就是说,CachedThreadPool中的线程也会被复用。

SingleThreadPool是线程数量为1的FixedThreadPool。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息