Java多线程 之 执行器Executor(二)
2016-06-01 22:01
381 查看
java多线程很少像前面的例子那样直接使用Thread.start()方法来驱动。而是使用执行器Executor来管理线程。执行器是启动任务的最佳方法。
ExecutorService(一个具有服务生命周期的执行器)知道如何创建恰当的上下文来执行Runnable对象。请看下面的例子(其中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。
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。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序