原文地址: 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. Android studio的那些bug

    R文件无法编译: 1.Activity继承类AppCompatActivity有时候会报错 2.R文件找不到一般是layout文件夹下出错 3.sdk包问题 4.Gradle DSL method n ...

  2. iOS bug 之 H5 页面没有弹出提示框

    描述:在安卓上有提示框,但是在iOS上没有提示框. step 1: 失误,是我没有在正确的位置设置网址. step 2: 修改之后,测试页能弹出提示框,但是正式的页面没有提示框. step 3: 我输 ...

  3. 如何设置打开jsp页面速度加快?

    1.

  4. dubbo框架揭秘之服务引用

    ApplicationConfig config = new ApplicationConfig("hello-worldp"); RegistryConfig reg = new ...

  5. PHP实现仿Google分页效果的分页函数

    本文实例讲述了PHP实现仿Google分页效果的分页函数.分享给大家供大家参考.具体如下: /** * 分页函数 * @param int $total 总页数 * @param int $pages ...

  6. Mac下启动MySQL出现错误“the /usr/local/mysql/data directory is not owned by the 'mysql' or '_mysql' user”解决

    错误如下: Warring the /usr/local/mysql/data directory is not owned by the 'mysql' or '_mysql' user 这应该是某 ...

  7. jq操作radio,设置选中、获取选中值

    <label><inputtype="radio"name="sex"value="1">男</label&g ...

  8. [Bullet3]创建世界(场景)及常见函数

    创建世界(场景)及常见函数 官方文档:http://bulletphysics.org 开源代码:https://github.com/bulletphysics/bullet3/releases A ...

  9. ubuntu服务器远程连接xshell,putty,xftp的简单使用教程

    当你自己千辛万苦终于搞到一个服务器(ubuntu(linux)系统的)之后,却不知道怎么进行时,xshell,putty,xftp是个很不错的选择 xshell和xftp是win下访问ubuntu(l ...

  10. HDU 2092 整数解

    整数解 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...