原文地址: 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 和线程池的更多相关文章

  1. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  2. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  3. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  4. Java并发编程:线程池的使用(转载)

    文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  5. [转]Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  6. 【转】Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  7. 13、Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  8. (转)Java并发编程:线程池的使用

    背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...

  9. Java并发编程之线程池及示例

    1.Executor 线程池顶级接口.定义方法,void execute(Runnable).方法是用于处理任务的一个服务方法.调用者提供Runnable 接口的实现,线程池通过线程执行这个 Runn ...

  10. Java并发编程:线程池ThreadPoolExecutor

    多线程的程序的确能发挥多核处理器的性能.虽然与进程相比,线程轻量化了很多,但是其创建和关闭同样需要花费时间.而且线程多了以后,也会抢占内存资源.如果不对线程加以管理的话,是一个非常大的隐患.而线程池的 ...

随机推荐

  1. PCA主成分分析方法

    PCA: Principal Components Analysis,主成分分析. 1.引入 在对任何训练集进行分类和回归处理之前,我们首先都需要提取原始数据的特征,然后将提取出的特征数据输入到相应的 ...

  2. CentOS6.5编译安装Redis

    一.首先要检测是否安装gcc yum install gcc-c++ yum install -y tcl 进入redis目录 cd /usr/local/redis .编译安装 make make ...

  3. archlinux初次接触遇到的问题

    arch-chroot /mnt /bin/bash ( 两个地址中间有空格)

  4. SqlParameter 使用

                SqlParameter[] param = new SqlParameter[]             {                 new SqlParameter ...

  5. java 二维码

    在http://www.ostools.net/qr看到了一个生成二维码的工具,于是就产生了一个想法: 为什么自己不做一个二维码的生成和解析工具呢?花了一个多钟的时间,嘿嘿,就做出来啦... 先来看看 ...

  6. Spring学习笔记IOC与AOP实例

    Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...

  7. jQuery动画高级用法(上)——详解animation中的.queue()动画队列插队函数

    决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fadeOut().slideUp().show().hide()诸如 ...

  8. [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据

    SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. 主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceS ...

  9. 用Linux命令行获取本机外网IP地址

    引言:目前获取ip的方法中,ifconfig和ip获取函数得到的都是内网ip.有时候需要获取外网ip,目前通用的做法,是向外部服务器发送请求,解析外部服务器响应,从而得到的自己的外网ip.linux下 ...

  10. 11g oracle 用户密码过期问题

    Oracle 11g 之前默认的用户时是没有密码过期的限制的,在Oracle 11g 中默认的profile启用了密码过期时间是180天.如下:select * from dba_profiles w ...