理解Thread Pool, Executor, Callable/Future

在JDK1.5版,Java标准包中就包含了对线程池的支持,提供了包java.lang.concurrent.

     

1. ThreadPool

    线程池是一个线程管理的集合,能够有效执行任务。当大量任务使用线程池执行时,由于线程循环的执行,整个性能得到提高,也减少了每个任务调用上的花费。实现线程池,你能够运用ExecutorService的实现类,比如ThreadPoolExecutor 或是ScheduledThreadPoolExecutor。另外,在类Executors 中提供了如下更方便的工厂方法:

  • Executors.newSingleThreadExecutor(): 创建一个单一后台线程实例.
  • Executors.newFixedThreadPool(int numThreads): 创建一个可以修复线程池大小实例.
  • Executors.newCachedThreadPool():运用自动化线程回收利用来创建一个非绑定线程池实例。

     使用线程池的步骤如下:

  1. 编写出实现了Runnable接口的工人线程类,run()方法指定了运行线程的行为。
  2. 使用由Executor类提供的工厂方法创建一个线程池(ExecutorService),这个线程池可以是 Executors.newSingleThreadExecutor(),或者Executors.newFixedThreadPool(int numThreads),也可以是Executors.newCachedThreadPool()创建的。
  3. 创建你的工人线程实例,使用execute(Runnable)方法去添加一个Runnable任务到线程池中。如何在池中有一个有效的线程,这个任务将会被调度并执行。
2. 理解相关API

    一个Executor对象能够执行Runnable提交的任务。Executor接口类(1.6version)中的方法:

[java]  view plain copy print ?
  1. void execute(Runnable command);  

   它在不久的某个时间里执行一个给予任务。

   接口ExecutorService定义了一些有用的方法,重要的两个如下:

[java]  view plain copy print ?
  1. public void shutdown();  
  2.    // Initiates an orderly shutdown of the thread pool.  
  3.    // The previously executed/submitted tasks are allowed to complete,  
  4.    // but no new tasks will be scheduled.  
  5. public <T> Future<T> submit(Callable<T> task);  
  6.    // Submit or schedule the callable task for execution, which returns a Future object.  

   Executors类中定义一些有用的方法:

[java]  view plain copy print ?
  1. static ExecutorService newSingleThreadExecutor()  
  2. static ExecutorService newFixedThreadPool(int nThreads)  
  3. static ExecutorService newCachedThreadPool()  
  4. static ScheduledExecutorService newSingleThreadScheduledExecutor()  
  5. static ScheduledExecutorService newScheduledThreadPool(int size)  

    一个简单的例子来说明一下如何调用使用线程池。

[java]  view plain copy print ?
  1. public class WorkerThread implements Runnable {  
  2.    private int workerNumber;  
  3.   
  4.    WorkerThread(int workerNumber) {  
  5.       this.workerNumber = workerNumber;  
  6.    }  
  7.   
  8.    public void run() {  
  9.       // The thread simply prints 1 to 5  
  10.       for (int i = 1; i <= 5; i++) {  
  11.          System.out.printf("Worker %d: %d\n", workerNumber, i);  
  12.          try {  
  13.             // sleep for 0 to 0.5 second  
  14.             Thread.sleep((int)(Math.random() * 500));  
  15.          } catch (InterruptedException e) {}  
  16.       }  
  17.    }  
  18. }  

[java]  view plain copy print ?
  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3.   
  4. public class ThreadPoolTest {  
  5.    public static void main(String[] args) {  
  6.       int numWorkers = Integer.parseInt(args[0]);  
  7.       int threadPoolSize = Integer.parseInt(args[1]);  
  8.   
  9.       ExecutorService pool =   
  10.             Executors.newFixedThreadPool(threadPoolSize);  
  11.       WorkerThread[] workers = new WorkerThread[numWorkers];  
  12.       for (int i = 0; i < numWorkers; i++) {  
  13.          workers[i] = new WorkerThread(i+1);  
  14.          pool.execute(workers[i]);  
  15.       }  
  16.       pool.shutdown();  
  17.    }  
  18. }  
    结果如下:
[plain]  view plain copy print ?
  1. Worker 1: 1  
  2. Worker 2: 1  
  3. Worker 2: 2  
  4. Worker 2: 3  
  5. Worker 2: 4  
  6. Worker 1: 2  
  7. Worker 1: 3  
  8. Worker 2: 5  
  9. Worker 1: 4  
  10. Worker 1: 5  
  11. Worker 3: 1  
  12. Worker 3: 2  
  13. Worker 4: 1  
  14. Worker 3: 3  
  15. Worker 3: 4  
  16. Worker 4: 2  
  17. Worker 3: 5  
  18. Worker 4: 3  
  19. Worker 5: 1  
  20. Worker 4: 4  
  21. Worker 5: 2  
  22. Worker 5: 3  
  23. Worker 4: 5  
  24. Worker 5: 4  
  25. Worker 5: 5  

    接口Callable和Runnable。 Callable与Runnable很相似。然而, Callable提供了一种能够固定在线程上的返回结果或是出现的异常。

       

[java]  view plain copy print ?
  1. public V call()  
  2.    // Call() returns a result of type <V>, or throws an exception if unable to do so.  
      

     在线程池中,使用submit(Callable r)可以返回一个Future<V>(在ExecutorService接口类中声明)对象。当需要有返回结果时,可以检索 get()方法来获得。如果不出现异常,会返回准备的结果。

     Future<V>的方法如下:

[java]  view plain copy print ?
  1. V get()           // wait if necessary, retrieve result  
  2. V get(long timeout, TimeUnit unit)  
  3. boolean cancel(boolean mayInterruptIfRunning)  
  4. boolean isCancelled()  
  5. boolean isDone()  // return true if this task completed  

    同样的例子,换一种写法:

    

[java]  view plain copy print ?
  1. public class CallableWorkerThread implements Callable<String> {  
  2.   
  3.     private int workerNumber;  
  4.   
  5.     CallableWorkerThread(int workerNumber) {  
  6.         this.workerNumber = workerNumber;  
  7.     }  
  8.   
  9.     public String call() {    // use call() instead of run()  
  10.         for (int i = 1; i <= 5; i++) {    // just print 1 to 5  
  11.             System.out.printf("Worker %d: %d\n", workerNumber, i);  
  12.             try {  
  13.                 Thread.sleep((int)(Math.random() * 1000));  
  14.             } catch (InterruptedException e) {}  
  15.         }  
  16.         return "worker " + workerNumber;  
  17.     }  
  18. }  

[java]  view plain copy print ?
  1. package org.concurrency.simple;  
  2.   
  3. /** 
  4.  * @author: John Liu 
  5.  */  
  6. import java.util.concurrent.*;  
  7.   
  8. public class CallableThreadPoolTest {  
  9.     public static void main(String[] args) {  
  10.         int numWorkers = 5;  
  11.   
  12.         ExecutorService pool = Executors.newCachedThreadPool();  
  13.         CallableWorkerThread workers[] = new CallableWorkerThread[numWorkers];  
  14.         Future[] futures = new Future[numWorkers];  
  15.   
  16.         for (int i = 0; i < numWorkers; i++) {  
  17.             workers[i] = new CallableWorkerThread(i + 1);  
  18.             futures[i] = pool.submit(workers[i]);  
  19.         }  
  20.         for (int i = 0; i < numWorkers; i++) {  
  21.             try {  
  22.                 System.out.println(futures[i].get() + " ended");  
  23.             } catch (InterruptedException ex) {  
  24.                 ex.printStackTrace();  
  25.             } catch (ExecutionException ex) {  
  26.                 ex.printStackTrace();  
  27.             }  
  28.         }  
  29.     }  
  30. }  

   结果:

[java]  view plain copy print ?
  1. Worker 21  
  2. Worker 41  
  3. Worker 51  
  4. Worker 11  
  5. Worker 31  
  6. Worker 42  
  7. Worker 43  
  8. Worker 22  
  9. Worker 44  
  10. Worker 52  
  11. Worker 12  
  12. Worker 32  
  13. Worker 45  
  14. Worker 53  
  15. Worker 23  
  16. Worker 54  
  17. Worker 33  
  18. Worker 13  
  19. Worker 24  
  20. Worker 14  
  21. Worker 34  
  22. Worker 55  
  23. Worker 25  
  24. Worker 15  
  25. Worker 35  
  26. worker 1 ended  
  27. worker 2 ended  
  28. worker 3 ended  
  29. worker 4 ended  
  30. worker 5 ended  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值