当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java Concurrency: ExecutorService Introduction

发表于: 2014-05-14   作者:DavyJones2010   来源:转载   浏览次数:
摘要: 1) Difference between Callable and Runnable      The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by anothe

1) Difference between Callable and Runnable

     The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception.

 

2) ExecutorService Intro

    "Executors are Java 5 name for the concept of thread pools. The 'Executor' naming is due to the fact that there is no guarantee that underlying implementation is actually a pool; an executor may be single-threaded or even synchronous".(From Spring Offical Doc)

    Example:

package edu.xmu.thread;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorTest
{
    public static void main(String[] args)
    {
        List<CalculationCallable> subThreadList = initSubThreadList();

        List<Future<Integer>> futures = new ArrayList<Future<Integer>>();

        ExecutorService pool = Executors.newFixedThreadPool(5);

        System.out.println("Start submit callable. Timestamp: "
                + System.currentTimeMillis());

        for (CalculationCallable calThread : subThreadList)
        {
            futures.add(pool.submit(calThread));
        }

        System.out
                .println("Finished submit callable. Start getFutures. Timestamp: "
                        + System.currentTimeMillis());

        int sum = 0;
        for (Future<Integer> future : futures)
        {
            try
            {
                sum += future.get();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        System.out.println("Finished getFutures. sum: " + sum + ", Timestamp: "
                + System.currentTimeMillis());
        pool.shutdown();
    }

    private static List<CalculationCallable> initSubThreadList()
    {
        CalculationCallable thread1 = new CalculationCallable(Arrays.asList(
                200, 200, 200, 200));
        CalculationCallable thread2 = new CalculationCallable(Arrays.asList(
                300, 300, 300, 300));
        CalculationCallable thread3 = new CalculationCallable(Arrays.asList(
                300, 300, 300, 300));
        CalculationCallable thread4 = new CalculationCallable(Arrays.asList(
                300, 300, 300, 300));
        CalculationCallable thread5 = new CalculationCallable(Arrays.asList(
                300, 300, 300, 300));

        List<CalculationCallable> subThreadList = new ArrayList<CalculationCallable>();
        subThreadList.add(thread1);
        subThreadList.add(thread2);
        subThreadList.add(thread3);
        subThreadList.add(thread4);
        subThreadList.add(thread5);

        return subThreadList;
    }
}

class CalculationCallable implements Callable<Integer>
{
    private List<Integer> numList;

    public CalculationCallable(List<Integer> numList)
    {
        super();
        this.numList = numList;
    }

    @Override
    public Integer call() throws Exception
    {
        int sum = 0;
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        for (int i : numList)
        {
            sum += i;
        }
        return sum;
    }
}

    Output:

Start submit callable. Timestamp: 1400053633686
Finished submit callable. Start getFutures. Timestamp: 1400053633687
Finished getFutures. sum: 5600, Timestamp: 1400053635687

// We can see that submit(Callable) will not cause execution of Callable.
// It just like a process of "register".
// And future.get() will start the execution process instead.
// And future.get() will start all the callables in the ExecutiveService(Pool)

    Attention:

        1> There is a disadvantage: If the first task takes a long time to compute and all the other tasks end before the first, the current thread cannot compute sum before the first task ends.

        2> Java has the solution for this, CompletionService.

    

    Extensions:

    public static void main(String[] args) throws InterruptedException
    {
        List<CalculationCallable> subThreadList = initSubThreadList();
        ExecutorService pool = Executors.newFixedThreadPool(5);

        System.out.println("Start submit callable. Timestamp: "
                + System.currentTimeMillis());

        List<Future<Integer>> futures = pool.invokeAll(subThreadList);

        System.out
                .println("Finished submit callable. Start getFutures. Timestamp: "
                        + System.currentTimeMillis());

        int sum = 0;
        for (Future<Integer> future : futures)
        {
            try
            {
                sum += future.get();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        System.out.println("Finished getFutures. sum: " + sum + ", Timestamp: "
                + System.currentTimeMillis());
        pool.shutdown();
    }

    Output:

Start submit callable. Timestamp: 1400661124891
Finished submit callable. Start getFutures. Timestamp: 1400661126892
Finished getFutures. sum: 5600, Timestamp: 1400661126892
// We will notice that invokeAll(Collection<?>..) will start the execution of all threads
// Instead of future.get(), we now bring the execution time forward.

    The source code snippet for invokeAll(Collection<? extends Callable<T>>)

for (Future<T> f : futures) {
  if (!f.isDone()) {
    try {
      f.get();
    } catch (CancellationException ignore) {
    } catch (ExecutionException ignore) {
    }
  }
}

 

 

3) CompletionService Intro

    Example:

public static void main(String[] args)
    {
        List<CalculationCallable> subThreadList = initSubThreadList();

        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        CompletionService<Integer> pool = new ExecutorCompletionService<Integer>(
                threadPool);

        System.out.println("Start submit callable. Timestamp: "
                + System.currentTimeMillis());

        for (CalculationCallable calThread : subThreadList)
        {
            pool.submit(calThread);
        }

        System.out
                .println("Finished submit callable. Start getFutures. Timestamp: "
                        + System.currentTimeMillis());

        int sum = 0;
        for (int i = 0; i < 5; i++)
        {
            try
            {
                sum += pool.take().get();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        System.out.println("Finished getFutures. sum: " + sum + ", Timestamp: "
                + System.currentTimeMillis());
        threadPool.shutdown();
    }

    Output:

Start submit callable. Timestamp: 1400054835960
Finished submit callable. Start getFutures. Timestamp: 1400054835961
Finished getFutures. sum: 5600, Timestamp: 1400054837961

// The CompletionService is based on ExecutorService to work.
// With that, you have the result in the order they are completed and you don't have to keep a collection of Future.

 

    

 

Reference Links:

1) http://baptiste-wicht.com/posts/2010/09/java-concurrency-part-7-executors-and-thread-pools.html

2) http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html

3) http://stackoverflow.com/questions/141284/the-difference-between-the-runnable-and-callable-interfaces-in-java

 

Java Concurrency: ExecutorService Introduction

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
1. 简介 1.1 多线程的好处 提高性能,提高吞吐量,开发多核CPU的性能; 使UI应答更顺畅 1.2 多线程的
【转】http://www.blogjava.net/vincent/archive/2009/07/16/287055.html 关于 Java Concurrency 自
对数据同步访问封装的策略 我们经常操作一些本身不是线程安全的对象时,在多线程的环境下就会考虑到
引言 以前有几次碰到过一个有意思的多线程问题,当时的场景看起来比较简单。有两个线程,他们都需要
1. Risks of Threads: 1> Safety Hazards We can add annotation: @NotThreadSafe, @ThreadSafe,
现在在CPU上,摩尔定律已经失效,大家都不再追求高频率,而是越来越追求多核,阿姆达尔定律似乎更重
Executor Executor仅仅是一个简单的接口,其定义如下 public interface Executor { void execute(Ru
Java technology 包括以下部分: The Java Programming Language The Java Platform 一、The Java P
1.Struts背后的运行机制 a.一个客户端在浏览器地址栏中输入了一个URL地址:http://localhost:8080/s
一、Exectuor框架简介 Java从1.5版本开始,为简化多线程并发编程,引入全新的并发编程包:java.util.
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号