ThreadPoolExecutor 的三种提交任务方式
学习内容:
ExecutorService线程池的应用...
1.如何创建线程池...
2.调用线程池的方法,获取线程执行完毕后的结果...
3.关闭线程...
首先我们先了解一下到底什么是线程池,只有了解了其中的道理,我们才能够进行应用...java.util.concurrent.ExecutorService表述了异步执行的机制
首先我们简单的举一个例子...

package executor; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Executor { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub System.out.println("cc");
ExecutorService executorService=Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
while(true){ System.out.println("aa");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
System.out.println("bb");
} }

这里我们指定了十个线程处于一个线程池内部,线程池的原理其实就是对多线程的一个管理,为了实现异步机制的一种方法,其实就是多个线程执行多个任务,最终这些线程通过线程池进行管理...不用手动去维护...一次可以处理多个任务,这样就可以迅速的进行相应...比如说一个网站成为了热点网站,那么对于大量的点击量,就必须要对每一次的点击做出迅速的处理,这样才能达到更好的交互效果...这样就需要多个线程去处理这些请求,以便能够更好的提供服务...
1. 简单的说一下如何创建线程池进行初始化....创建线程有几种常用方式...这里都是使用了Executors工厂来实例化对象,同时我们也可以根据需求自己去写一个ExecutorService...这几种常用的方法有一定的区别...
ExecutorService executorService1 = Executors.newSingleThreadExecutor(); ExecutorService executorService2 = Executors.newFixedThreadPool(10); ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
ExecutorService executorService4 = Executors.newCacheThreadPool();
Executors.newSingleThreadExecutor() |
单例线程,表示在任意的时间段内,线程池中只有一个线程在工作... |
Executors.newCacheThreadPool() |
缓存线程池,先查看线程池中是否有当前执行线程的缓存,如果有就resue(复用),如果没有,那么需要创建一个线程来完成当前的调用.并且这类线程池只能完成一些生存期很短的一些任务.并且这类线程池内部规定能resue(复用)的线程,空闲的时间不能超过60s,一旦超过了60s,就会被移出线程池. |
| Executors.newFixedThreadPool(10) | 固定型线程池,和newCacheThreadPool()差不多,也能够实现resue(复用),但是这个池子规定了线程的最大数量,也就是说当池子有空闲时,那么新的任务将会在空闲线程中被执行,一旦线程池内的线程都在进行工作,那么新的任务就必须等待线程池有空闲的时候才能够进入线程池,其他的任务继续排队等待.这类池子没有规定其空闲的时间到底有多长.这一类的池子更适用于服务器. |
| Executors.newScheduledThreadPool(10) |
调度型线程池,调度型线程池会根据Scheduled(任务列表)进行延迟执行,或者是进行周期性的执行.适用于一些周期性的工作. |
这就是线程池创建的几种方式...我们需要根据不同的需求来适当的选择到底使用哪种线程池...
2.那么创建了线程池以后就需要对线程池进行调用..将任务加载到其中...
i.ExecutorService.execute(Runnable);
第一种调用方式...通过这种方式将线程任务加载到线程池当中...我们可以添加多个任务...贴上一个完整的代码...大家看一下代码的解释就明白到底是怎么回事了..不难理解...

package executor; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Executor { /**
* @param args
*
*/ public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService executorService=Executors.newFixedThreadPool(2);//定义了线程池中最大存在的线程数目... //添加了第一个任务...这个任务会一直被执行...
executorService.execute(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
while(true){ System.out.println("aa");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}); //添加第二个任务,被执行三次停止...
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
while(true){
i++;
System.out.println("bb");
if(i==3){
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}); /*
* @param
* 第三个任务...只有当第二个任务被执行三次之后才能被执行...
* 由于三次前,线程池已经满了,这个任务是轮不到被执行的..只能排队进行等待.
* 三次之后,第二个任务被终止,也就是线程池中出现了空闲的状态,所以这个任务将被放入到线程池中执行...
* */
executorService.execute(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
while(true){ System.out.println("cc");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
} }

ii.executorService.submit(Runnable) 第二种调用方式...这种方式与第一种的区别在于可以使用一个Future对象来判断当前的线程是否执行完毕...但是这种方法只能判断当前的线程是否执行完毕,无法返回数据信息...

Future future = executorService.submit(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
//如果任务结束执行则返回 null
System.out.println("future.get()=" + future.get());

iii.executorService.submit(Callable)... 第三种调用方式...这种调用方式与前一种有所不同,传递的参数为Callable对象,Callable与Runnbale很相似,但是Callable的call()方法可以返回数据信息...通过Future就能够获取到其中的信息..而Runnbale.run()方法时无法获取数据信息的....Future应用于多线程...可以获取call()方法返回的数据信息...其实他是一种模式,是为了性能优化而提供的一种思想...这里我就不说Future...

uture 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());
//上述样例代码会输出如下结果:
//Asynchronous Callable
//future.get() = Callable Result

iv.inVokeAny()...第四种调用方式...方法 invokeAny() 接收一个包含 Callable 对象的集合作为参数。调用该方法不会返回 Future 对象,而是返回集合中某一个 Callable 对象的结果,而且无法保证调用之后返回的结果是哪一个Callable,只知道它是这些 Callable 中一个执行结束的 Callable 对象...说实话这个方法我不知道它创建的目的到底是什么...这里执行后的结果是随机的...也就是输出是不固定的....

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);

v.inVokeAll()这个方法和上面不同的地方就在于它可以返回所有Callable的执行结果...获取到所有的执行结果,我们可以对其进行管理...相对而言,我觉得这个方法比上一个更实用吧...

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());

3.线程池的关闭...
当我们不需要使用线程池的时候,我们需要对其进行关闭...有两种方法可以关闭掉线程池...
i.shutdown()...
shutdown并不是直接关闭线程池,而是不再接受新的任务...如果线程池内有任务,那么把这些任务执行完毕后,关闭线程池....
ii.shutdownNow()
这个方法表示不再接受新的任务,并把任务队列中的任务直接移出掉,如果有正在执行的,尝试进行停止...
大家自己试着运行下面的代码就了解其中到底是怎么回事了...

package executor; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Executor { /**
* @param args
*
*/ public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService executorService=Executors.newFixedThreadPool(1);//定义了线程池中最大存在的线程数目... //添加了第一个任务...这个执行三次停止...
executorService.execute(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
int j=0;
while(true){
j++;
System.out.println("aa");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(j==3){
break;
}
}
}
}); //添加第二个任务,由于使用executorService.shutdown(),由于它的加入是在这个方法调用之前的,因此这个任务也会被执行...
//如果我们使用了executorService.shutdownNow();方法,就算是他在之前加入的,由于调用了executorService.shutdownNow()方法
//那么这个任务将直接被移出队列并且不会被执行...
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
while(true){
i++;
System.out.println("bb");
if(i==3){
break;
}
}
}
});
executorService.shutdown();//这里无论使用了那种方法,都会抛出一个异常...
/*
* @param
* 第三个任务...只有当第二个任务被执行三次之后才能被执行...
* 由于三次前,线程池已经满了,这个任务是轮不到被执行的..只能排队进行等待.
* 三次之后,第二个任务被终止,也就是线程池中出现了空闲的状态,所以这个任务将被放入到线程池中执行...
* */
executorService.execute(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
while(true){ System.out.println("cc");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
} }

ThreadPoolExecutor 的三种提交任务方式的更多相关文章
- javascript 中数组的创建 添加 与将数组转换成字符串 页面三种提交请求的方式
创建js数组 var array=new Array(); Java中创建数组 private String[] array=new String[3]; 两个完全不同的,js中是可变长度的 添加内容 ...
- Apache Spark探秘:三种分布式部署方式比较
转自:链接地址: http://dongxicheng.org/framework-on-yarn/apache-spark-comparing-three-deploying-ways/ 目 ...
- VMware的三种网络连接方式区别
关于VMware的三种网络连接方式,NAT,Bridged,Host-Only ,在刚接触的时候通常会遇到主机Ping不通虚拟机而虚拟机能Ping得通主机:主机与虚拟机互不相通等等网络问题.本文就这三 ...
- .NET中的三种接口实现方式
摘自:http://www.cnblogs.com/zhangronghua/archive/2009/11/25/1610713.html 一般来说.NET提供了三种不同的接口实现方式,分别为隐式接 ...
- [转]详述DHCP服务器的三种IP分配方式
DHCP就是动态主机配置协议(Dynamic Host Configuration Protocol),它的目的就是为了减轻TCP/IP网络的规划.管理和维护的负担,解决IP地址空间缺乏问题.这种网络 ...
- Binding 中 Elementname,Source,RelativeSource 三种绑定的方式
在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...
- windows phone 三种数据共享的方式(8)
原文:windows phone 三种数据共享的方式(8) 本节实现的内容是数据共享,实现的效果描述:首先是建立两个页面,当页面MainPage通过事件导航到页面SecondPage是,我们需要将Ma ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探
更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...
- Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress(转发)
原文 http://cloud.51cto.com/art/201804/570386.htm Kubernetes的三种外部访问方式:NodePort.LoadBalancer和Ingress 最近 ...
随机推荐
- PHP性能追踪及分析工具xhprof的安装与使用
对于本地开发环境来说,进行性能分析xdebug是够用了,但如果是线上环境的话,xdebug消耗较大,配置也不够灵活,因此线上环境建议使用xhprof进行PHP性能追踪及分析. 我们今天就简单介绍一下x ...
- Ubuntu下查看CPU、内存和硬盘详细信息的几个命令
CPU: 型号:grep "model name" /proc/cpuinfo |awk -F ':' '{print $NF}' 数量:lscpu |grep "CPU ...
- [ 总结 ] nginx 负载均衡 及 缓存
操作系统:centos6.4 x64 前端使用nginx做反向代理,后端服务器为:apache + php + mysql 1. nginx负载均衡. nginx编译安装(编译安装前面的文章已经写过) ...
- python gui tkinter用法杂记
1.treeview遍历 iids = tree.selection() t = tree.get_children() for i in t: print(tree.item(i,'values') ...
- 在使用Arduino中遇到的问题(无法使用中文注释、程序无法下载)
在使用Arduino中遇到的问题: 在用arduino给蓝牙模块供电时,下载程序是下不进去的.即使显示下进去了,其实也是没下进去. 解决方法:拔掉蓝牙模块再下程序,或给蓝牙供电的线上加上一个开关. 在 ...
- ubuntu 18.04下安装编译的KMS,依赖库
libboost-system1.65.1 libglib2.0-0 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 libnice10 libsig ...
- Codeforces 538 C. Tourist's Notes
C. Tourist's Notes time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- HDU 5695 Gym Class && 百度之星 初赛 1006
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5695 本文链接:http://www.cnblogs.com/Ash-ly/p/5515234.htm ...
- 洛谷——P1405 苦恼的小明
P1405 苦恼的小明 题目描述 黄小明和他的合伙人想要创办一所英语培训机构,注册的时候要填一张个人情况的表格,在身高一栏小明犯了愁. 身高要求精确到厘米,但小明实在太高了,无法在纸上填下这么长的数字 ...
- hihocoder1069 最近公共祖先·三(tarjin算法)(并查集)
#1069 : 最近公共祖先·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的“最近公共祖先”网站,但是 ...