线程池ExecutorService
说到java开发,免不了跟多线程打交道。Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结束之前开始执行,此时可能会访问到初始化了一半的对象用Executor在构造器中。
ExecutorService,是一个接口,继承了Executor;
Executor,只有一个方法:
public interface Executor {
void execute(Runnable command);
}
Executors提供了4中创建线程池:
public static ExecutorService newCachedThreadPool(); 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public static ExecutorService newFixedThreadPool(int nThreads); 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建一个定长线程池,支持定时及周期性任务执行。
public static ExecutorService newSingleThreadExecutor(); 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
通过Executors的以上四个静态工厂方法获得 ExecutorService实例,而后调用该实例的execute(Runnable command)方法即可。一旦Runnable任务传递到execute()方法,该方法便会自动在一个线程上执行。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ExecutorTest {
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
//ExecutorService executorService = Executors.newFixedThreadPool(3);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++){
RunnableTest method = new RunnableTest();
executorService.execute(method);
System.out.println("########" + i + "########");
}
executorService.shutdown();
}
}
public class RunnableTest implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName() + "线程执行");
}
}
输出结果:
########0########
########1########
########2########
pool-1-thread-2线程执行
pool-1-thread-3线程执行
pool-1-thread-1线程执行
任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被ExecutorService执行,但是Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的submit(Callable<T> task) 方法来执行,并且返回一个 <T>Future<T>,是表示任务等待完成的 Future。
下面给出一个Executor执行Callable任务的示例代码
public class ExecutorTest {
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
//ExecutorService executorService = Executors.newFixedThreadPool(3);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
List<Future<String>> resultList = new ArrayList<Future<String>>();
for (int i = 0; i < 6; i++){
CallableTest method = new CallableTest(i);
Future<String> future = executorService.submit(method);
System.out.println("########" + i + "########");
resultList.add(future);
}
//遍历任务的结果
for (Future<String> fs : resultList){
try{
//Future返回如果没有完成,则一直循环等待,直到Future返回完成
while(!fs.isDone());
//打印各个线程(任务)执行的结果
System.out.println(fs.get());
}catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{
//启动一次顺序关闭,执行以前提交的任务,但不接受新任务
executorService.shutdown();
}
}
}
}
import java.util.concurrent.Callable;
public class CallableTest implements Callable<String>{
private int id;
public CallableTest(int id){
this.id = id;
}
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + "线程执行");
return Thread.currentThread().getName() + "线程执行" + "返回id=" + id;
}
}
输出结果:
pool-1-thread-1线程执行返回id=0
pool-1-thread-2线程执行返回id=1
pool-1-thread-3线程执行返回id=2
pool-1-thread-4线程执行返回id=3
pool-1-thread-2线程执行返回id=4
pool-1-thread-4线程执行返回id=5
从结果中可以同样可以看出,submit也是首先选择空闲线程来执行任务,如果没有,才会创建新的线程来执行任务。另外,需要注意:如果Future的返回尚未完成,则get()方法会阻塞等待,直到Future完成返回,可以通过调用isDone()方法判断Future是否完成了返回。
线程池ExecutorService的更多相关文章
- PAIP.并发编程 多核编程 线程池 ExecutorService的判断线程结束
PAIP.并发编程 多核编程 线程池 ExecutorService的判断线程结束 ExecutorService并没有提供什么 isDone()或者isComplete()之类的方法. 作者Atti ...
- [Java线程] Java线程池ExecutorService
示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.u ...
- 【Java线程】Java线程池ExecutorService
示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.u ...
- Java线程池ExecutorService和CountDownLatch的小例子
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java ...
- 多线程 线程池 ExecutorService
package org.zln.thread; import java.util.Date; import java.util.concurrent.ExecutorService; import j ...
- Java中的线程池ExecutorService
示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.u ...
- (转)线程池 ExecutorService 详细介绍以及注意点区别
线程池 ExecutorService 相信java开发都用到,这里做个简单笔记 一 Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池 ...
- 线程池(ExecutorService)初体验
背景:查询月统计数据,因为查询日统计数据功能已经实现.月统计数据,只是参一个List(date) 参数,for循环调用日统计,然后把结果整合就OK. 问题:单线程跑 太耗时间 解决方案:使用多线程, ...
- 线程池ExecutorService的使用及其正确关闭方法
创建一个容量为5的线程池 ExecutorService executorService = Executors.newFixedThreadPool(5); 向线程池提交15个任务,其实就是通过线程 ...
随机推荐
- c++截取英文和汉字(单双字节)混合字符串
在C++里截取字符串可以使用CString.Mid(),可是这个函数只能按英文(单字节)来截取, 如果是汉字可能就要计算好字符个数,如果是汉字和英文混合,那就没辙了. 可是恰好我需要这样一个函数,于是 ...
- vim 标记 mark 详解 (转载)
http://www.cnblogs.com/jianyungsun/archive/2011/02/14/1954057.html Vim 允许你在文本中放置自定义的标记.命令 "ma&q ...
- JavaIO之File类
Java-IO之File类 Java-IO之File类 1. File类 1.1. File类说明 1.2. 体验 File 类 1.3. 构造一个 File 类实例: 1.4. 路径: 1.4.1. ...
- 决策树(含python源代码)
因为最近实习的需要,所以用python里的sklearn包重新写了一次决策树 工具:sklearn,http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy:将 ...
- js自定义对象
一,概述 在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 目前在Javascrip ...
- js 两数相减
var SecondPrice = document.getElementById("txtSecondPrice"); //秒杀价 var MarketP ...
- PHP操作Mongodb之增删改查篇
之前,我讲解过PHP中mongodb扩展的安装,及启动,链接操作[忘记了?去看看吧!PHP操作Mongodb之一].本文主要就是讲在PHP中Mongodb的增加,查询,修改及删除数据的操作. 1.增加 ...
- 【Debian】非法关机后无法联网 connect: network is unreachable
某一天,突然发现无法ssh登录虚拟机内的debian系统,一直认为是ssh的问题,然后无意间ping了ping百度,发现原来是debian系统没有联网....囧 首先,是虚拟机的网络设置检查. 打开V ...
- Javascript.Reactjs-5-prop-validation-and-proptypes
Props & PropTypes 1. Props "Props are the mechanism React uses to let components communicat ...
- <停车位>version1.0
<停车卫> 产品需求说明书 文档版本号: Version 1.0 文档编号: xxxx 文档密级: 归属部门/项目: 产品名: 停车卫 子系统名: 编写人: kina 编写日期: 2015 ...