【转】Java 并发:Executors 和线程池
原文地址: http://baptiste-wicht.com/posts/2010/09/java-concurrency-part-7-executors-and-thread-pools.html
Java Concurrency - Part 7 : Executors and thread pools
Let's start with a new post in the Java concurrency series.
This time we'll learn how to start cleanly new threads and to manage thread pools. In Java, if you have a Runnable like this :
Runnable runnable = new Runnable(){
public void run(){
System.out.println("Run");
}
}
You can easily run it in a new thread :
new Thread(runnable).start();
This is very simple and clean, but what if you've several long running tasks that you want to load in parralel and then wait for the completion of all the tasks, it's a little bit harder to code and if you want to get the return value of all the tasks it becomes really difficult to keep a good code. But like for almost any problems, Java has a solution for you, the Executors. This simple class allows you to create thread pools and thread factories.
A thread pool is represented by an instance of the class ExecutorService. With an ExecutorService, you can submit task that will be completed in the future. Here are the type of thread pools you can create with the Executors class :
- Single Thread Executor : A thread pool with only one thread. So all the submitted task will be executed sequentially. Method :Executors.newSingleThreadExecutor()
- Cached Thread Pool : A thread pool that create as many threads it needs to execute the task in parralel. The old available threads will be reused for the new tasks. If a thread is not used during 60 seconds, it will be terminated and removed from the pool. Method : Executors.newCachedThreadPool()
- Fixed Thread Pool : A thread pool with a fixed number of threads. If a thread is not available for the task, the task is put in queue waiting for an other task to ends. Method : Executors.newFixedThreadPool()
- Scheduled Thread Pool : A thread pool made to schedule future task. Method : Executors.newScheduledThreadPool()
- Single Thread Scheduled Pool : A thread pool with only one thread to schedule future task. Method :Executors.newSingleThreadScheduledExecutor()
Once you have a thread pool, you can submit task to it using the different submit methods. You can submit a Runnable or a Callableto the thread pool. The method return a Future representing the future state of the task. If you submitted a Runnable, the Future object return null once the task finished.
By example, if you have this Callable :
private final class StringTask implements Callable<String> {
public String call(){
//Long operations
return "Run";
}
}
If you want to execute that task 10 times using 4 threads, you can use that code :
ExecutorService pool = Executors.newFixedThreadPool(4);
for(int i = 0; i < 10; i++){
pool.submit(new StringTask());
}
But you must shutdown the thread pool in order to terminate all the threads of the pool :
pool.shutdown();
If you don't do that, the JVM risk to not shutdown because there is still threads not terminated. You can also force the shutdown of the pool using shutdownNow, with that the currently running tasks will be interrupted and the tasks not started will not be started at all.
But with that example, you cannot get the result of the task. So let's get the Future objects of the tasks :
ExecutorService pool = Executors.newFixedThreadPool(4);
List<Future<String>> futures = new ArrayList<Future<String>>(10);
for(int i = 0; i < 10; i++){
futures.add(pool.submit(new StringTask()));
}
for(Future<String> future : futures){
String result = future.get();
//Compute the result
}
pool.shutdown();
But this code is a bit complicated. And there is a disadvantage. If the first task takes a long time to compute and all the other tasks ends before the first, the current thread cannot compute the result before the first task ends. Once again, Java has the solution for you, CompletionService.
A CompletionService is a service that make easier to wait for result of submitted task to an executor. The implementation is ExecutorCompletionService who's based on an ExecutorService to work. So let's try :
ExecutorService threadPool = Executors.newFixedThreadPool(4);
CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);
for(int i = 0; i < 10; i++){
pool.submit(new StringTask());
}
for(int i = 0; i < 10; i++){
String result = pool.take().get();
//Compute the result
}
threadPool.shutdown();
With that, you have the result in the order they are completed and you don't have to keep a collection of Future.
Here we are, you have the tools in hand to launch tasks in parralel using performing thread pools. Using Executors, ExecutorService and CompletionService you can create complex algorithm using several taks. With that tools, it's really easy to change the number of threads performing in parralel or adding more tasks without changing a lot of code.
I hope that this post will help you to write better concurrent code.
参考:
ThreadPoolExecutor使用和思考:http://dongxuan.iteye.com/blog/901689
【转】Java 并发:Executors 和线程池的更多相关文章
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- Java并发编程:线程池的使用(转载)
文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- [转]Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 【转】Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 13、Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程之线程池及示例
1.Executor 线程池顶级接口.定义方法,void execute(Runnable).方法是用于处理任务的一个服务方法.调用者提供Runnable 接口的实现,线程池通过线程执行这个 Runn ...
- Java并发编程:线程池ThreadPoolExecutor
多线程的程序的确能发挥多核处理器的性能.虽然与进程相比,线程轻量化了很多,但是其创建和关闭同样需要花费时间.而且线程多了以后,也会抢占内存资源.如果不对线程加以管理的话,是一个非常大的隐患.而线程池的 ...
随机推荐
- android 通过wifi 热点实现手机摄像头数据共享(转)
原文地址:http://blog.csdn.net/sinat_35845281/article/details/52674946 最近想搞一个新奇的玩意儿~~~ 最近一直在在学习通过两个Androi ...
- UVa 11308 - Bankrupt Baker
题目大意:给出一些原料和价钱和若干份菜谱,每份菜谱都标明所需的原料和数量,找出所有不超过预算的菜谱. 没什么好说的,主要是对map的运用. #include <cstdio> #inclu ...
- 【Android】Activity
一.Android四大组件 Activity.Service.BroadCastReceiver.ContentProvider. 二.Activity的继承关系 三.建立.配置和使用Activity ...
- simplexml 对xml的增删改操作
simplexml 是php 处理xml 文件的一个方法,另一个是dom 处理,这里只说simplexml .目前php 处理xml 用的比较多,比较成熟的还是dom .但dom 在速度和代码量上还是 ...
- mysql 和excel相互转换
原文地址:http://blog.sina.com.cn/s/blog_43eb83b90100h0mc.html 今天是全国数学建模比赛,同学选的一个题目需要对一个large的Excel表格进行统计 ...
- 3.1. 修改托管对象模型(Core Data 应用程序实践指南)
托管对象模型是会变好的,有时候变化的比较小,什么添加验证规则.修改默认值.修改获取请求模板等.但是设置到结构变化,如添加.删除字段时,需要先把持久化数据区迁移到新的模型版本才行.假如没有提供迁移数据所 ...
- 在DFS和BFS中一般情况可以不用vis[][]数组标记
开始学dfs 与bfs 时一直喜欢用vis[][]来标记有没有访问过, 现在我觉得没有必要用vis[][]标记了 看代码 用'#'表示墙,'.'表示道路 if(所有情况都满足){ map[i][j]= ...
- AdapterViewFlipper的功能和用法
AdapterView继承了AdapterViewAnimator,它也会显示Adapter提供的多个View组件,但每次只能显示一个View组件,程序可通过showPrevious和showNext ...
- CSS的position设置
CSS的position设置: <%@ page language="java" contentType="text/html; charset=UTF-8&quo ...
- 在ASP.NET Core下使用SignalR技术
一.前言 上次我们讲到过如何在ASP.NET Core中使用WebSocket,没有阅读过的朋友请参考 WebSocket in ASP.NET Core 文章 .这次的主角是SignalR它为我们提 ...