每次new Thread()耗费性能
调用new Thread()建立的线程缺少管理,被称为野线程,并且能够无限制建立,之间相互竞争,会致使过多占用系统资源致使系统瘫痪。
不利于扩展,好比如定时执行、按期执行、线程中断javascript
重用存在的线程,减小对象建立、消亡的开销,性能佳
可有效控制最大并发线程数,提升系统资源的使用率,同时避免过多资源竞争,避免堵塞
提供定时执行、按期执行、单线程、并发数控制等功能html
在Java 5以后,并发编程引入了一堆新的启动、调度和管理线程的API。java
其内部使用了线程池机制,它在java.util.cocurrent 包下,经过该框架来控制线程的启动、执行和关闭,能够简化并发编程的操做。所以,在Java 5以后,经过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——若是咱们在构造器中启动一个线程,由于另外一个任务可能会在构造器结束以前开始执行,此时可能会访问到初始化了一半的对象用Executor在构造器中。面试
Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。编程
经过Executors提供四种线程池,newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool。缓存
1.public static ExecutorService newFixedThreadPool(int nThreads)
建立固定数目线程的线程池。服务器
2.public static ExecutorService newCachedThreadPool()
建立一个可缓存的线程池,调用execute将重用之前构造的线程(若是线程可用)。若是现有线程没有可用的,则建立一个新线 程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。微信
3.public static ExecutorService newSingleThreadExecutor()
建立一个单线程化的Executor。markdown
4.public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
建立一个支持定时及周期性的任务执行的线程池,多数状况下可用来替代Timer类。多线程
示例
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 20; i++) {
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
}
};
executorService.execute(syncRunnable);
}
运行结果:总共只会建立5个线程, 开始执行五个线程,当五个线程都处于活动状态,再次提交的任务都会加入队列等到其余线程运行结束,当线程处于空闲状态时会被下一个任务复用
示例:
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
}
};
executorService.execute(syncRunnable);
}
运行结果:能够看出缓存线程池大小是不定值,能够须要建立不一样数量的线程,在使用缓存型池时,先查看池中有没有之前建立的线程,若是有,就复用.若是没有,就新建新的线程加入池中,缓存型池子一般用于执行一些生存期很短的异步型任务
schedule(Runnable command,long delay, TimeUnit unit)建立并执行在给定延迟后启用的一次性操做
示例:表示从提交任务开始计时,5000毫秒后执行
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 20; i++) {
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
}
};
executorService.schedule(syncRunnable, 5000, TimeUnit.MILLISECONDS);
}
运行结果和newFixedThreadPool相似,不一样的是newScheduledThreadPool是延时必定时间以后才执行
建立并执行一个在给定初始延迟后首次启用的按期操做,后续操做具备给定的周期;也就是将在 initialDelay 后开始执行,而后在initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
}
};
executorService.scheduleAtFixedRate(syncRunnable, 5000, 3000, TimeUnit.MILLISECONDS);
建立并执行一个在给定初始延迟后首次启用的按期操做,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
executorService.scheduleWithFixedDelay(syncRunnable, 5000, 3000, TimeUnit.MILLISECONDS);
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 20; i++) {
Runnable syncRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, Thread.currentThread().getName());
}
};
executorService.execute(syncRunnable);
}
运行结果:只会建立一个线程,当上一个执行完以后才会执行第二个
public interface ExecutorService extends Executor {
void shutdown();//顺次地关闭ExecutorService,中止接收新的任务,等待全部已经提交的任务执行完毕以后,关闭ExecutorService
List<Runnable> shutdownNow();//阻止等待任务启动并试图中止当前正在执行的任务,中止接收新的任务,返回处于等待的任务列表
boolean isShutdown();//判断线程池是否已经关闭
boolean isTerminated();//若是关闭后全部任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,不然 isTerminated 永不为 true。
boolean awaitTermination(long timeout, TimeUnit unit)//等待(阻塞)直到关闭或最长等待时间或发生中断,timeout - 最长等待时间 ,unit - timeout 参数的时间单位 若是此执行程序终止,则返回 true;若是终止前超时期满,则返回 false
<T> Future<T> submit(Callable<T> task);//提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。
<T> Future<T> submit(Runnable task, T result);//提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。
Future<?> submit(Runnable task);//提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功 完成时将会返回 null
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)//执行给定的任务,当全部任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的全部元素的 Future.isDone() 为 true。
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)//执行给定的任务,当全部任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的全部元素的 Future.isDone() 为 true。
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;
}
ExecutorService接口继承自Executor接口,它提供了更丰富的实现多线程的方法,好比,ExecutorService提供了关闭本身的方法,以及可为跟踪一个或多个异步任务执行情况而生成 Future 的方法。 能够调用ExecutorService的shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将致使ExecutorService中止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另外一类是尚未开始执行的),当全部已经提交的任务执行完毕后将会关闭ExecutorService。所以咱们通常用该接口来实现和管理多线程。
ExecutorService的生命周期包括三种状态:运行、关闭、终止。建立后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService再也不接受新的任务,但它还在执行已经提交了的任务,当素有已经提交了的任务执行完后,便到达终止状态。若是不调用shutdown()方法,ExecutorService会一直处在运行状态,不断接收新的任务,执行新的任务,服务器端通常不须要关闭它,保持一直运行便可。
一旦Runnable任务传递到execute()方法,该方法便会自动在一个线程上执行。下面是是Executor执行Runnable任务的示例代码:
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() + "线程被调用了。");
}
}
在Java 5以后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。二者均可以被ExecutorService执行,可是Runnable任务没有返回值,而Callable任务有返回值。而且Callable的call()方法只能经过ExecutorService的submit(Callable task) 方法来执行,而且返回一个 Future,是表示任务等待完成的 Future。
public class CallableDemo{
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
//建立10个任务并执行
for (int i = 0; i < 10; i++){
//使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = executorService.submit(new TaskWithResult(i));
//将任务执行结果存储到List中
resultList.add(future);
}
//遍历任务的结果
for (Future<String> fs : resultList){
try{
while(!fs.isDone);//Future返回若是没有完成,则一直循环等待,直到Future返回完成
System.out.println(fs.get()); //打印各个线程(任务)执行的结果
}catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{
//启动一次顺序关闭,执行之前提交的任务,但不接受新任务
executorService.shutdown();
}
}
}
}
class TaskWithResult implements Callable<String>{
private int id;
public TaskWithResult(int id){
this.id = id;
}
/** * 任务的具体过程,一旦任务传给ExecutorService的submit方法, * 则该方法自动在一个线程上执行 */
public String call() throws Exception {
System.out.println("call()方法被自动调用!!! " + Thread.currentThread().getName());
//该返回结果将被Future的get方法获得
return "call()方法被自动调用,任务返回的结果是:" + id + " " + Thread.currentThread().getName();
}
}
从结果中能够一样能够看出,submit也是首先选择空闲线程来执行任务,若是没有,才会建立新的线程来执行任务。另外,须要注意:若是Future的返回还没有完成,则get()方法会阻塞等待,直到Future完成返回,能够经过调用isDone()方法判断Future是否完成了返回。
自定义线程池,能够用ThreadPoolExecutor类建立,它有多个构造方法来建立线程池,用该类很容易实现自定义的线程池,这里先贴上示例程序:
public class ThreadPoolTest{
public static void main(String[] args){
//建立等待队列
BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
//建立线程池,池中保存的线程数为3,容许的最大线程数为5
ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50,TimeUnit.MILLISECONDS,bqueue);
//建立七个任务
Runnable t1 = new MyThread();
Runnable t2 = new MyThread();
Runnable t3 = new MyThread();
Runnable t4 = new MyThread();
Runnable t5 = new MyThread();
Runnable t6 = new MyThread();
Runnable t7 = new MyThread();
//每一个任务会在一个线程上执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
pool.execute(t7);
//关闭线程池
pool.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "正在执行。。。");
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
http://gold.xitu.io/entry/57cbaf667db2a2007895256e
http://blog.csdn.net/ns_code/article/details/17465497
http://www.infoq.com/cn/articles/executor-framework-thread-pool-task-execution-part-01
http://www.cnblogs.com/limingluzhu/p/4858776.html