最近在处理很多的数据,数据量比较大,但是处理的相对简单一些,没有什么复杂的业务逻辑,然后就使用了多线程去处理。因为一直停留在Thread和Runnable的知识中,项目中使用Callable,刚好可以学习新的东西,就使用了Callable和Future结合加上Executors.newFixedThreadPool()。

一、Callable和Future基础知识

  Thread和Runnable这2个很多人都知道并且使用过,可能Callable相对陌生一些,future应该更加陌生,他们2个一个生成结果一个接受结果。Thread和Runnable实现的线程不会返回结果,Callable相对特殊一些,他会返回结果,这个结果可以被Future拿到,也就是说,Future可以拿到异步执行任务的结果。我们先看一下Callable类:

  1. package java.util.concurrent;
  2.  
  3. /**
  4. *一个带有返回结果并可能引发异常的任务.实现定义了一个没有调用参数
  5. *的方法call。
  6. *Callable接口类似于{@link java.lang.Runnable},因为它们都是为其
  7. *实例可能被另一个线程执行的类设计的。然而,Runnable不返回结果,
  8. *也不能抛出被检查的异常。{@link Executors}类包含从其他常用形式
  9. *转换为Callable类的实用程序方法。
  10. */
  11. public interface Callable<V> {
  12.  
  13. /**
  14. * 计算一个结果,如果不能这样做,就会抛出一个异常。.
  15. *
  16. * @return 结算结果
  17. * @throws 如果无法计算结果,则抛出异常
  18. */
  19. V call() throws Exception;
  20. }

  Future表示一个任务的生命周期,并提供了方法来判断是否已经完成或取消,以及获取任务的结果和取消任务等。Future接口:

  1. public interface Future<V> {
  2.  
  3. /**
  4. * 尝试取消执行此任务。 如果任务已经完成,已经被取消或由于某种其他原因而无法取消,则此尝试将失败。
  5. * 如果成功,并且调用<tt> cancel </ tt>时,此任务尚未启动,则此任务不应运行。 如果任务已经开始,
  6. * 那么<tt> mayInterruptIfRunning </ tt>参数决定了执行该任务的线程是否应该被中断以试图停止该任务。
  7. */
  8. boolean cancel( boolean mayInterruptIfRunning );
  9.  
  10. /**
  11. * 如果此任务在正常完成之前已被取消,返回true
  12. * @return <tt>true</tt> 如果此任务在正常完成之前已被取消,返回true
  13. */
  14. boolean isCancelled();
  15.  
  16. /**
  17. * 如果任务已经完成返回true
  18. * 完成可能是由于正常终止,异常或异常 - 在所有这些情况下,此方法都将返回<tt> true </ tt>。
  19. * @return <tt>true</tt> 如果任务已经完成返回true
  20. */
  21. boolean isDone();
  22.  
  23. /**
  24. * 等待计算完成,然后获得其结果。
  25. *
  26. */
  27. V get() throws InterruptedException, ExecutionException;
  28.  
  29. /**
  30. * 如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。
  31. *
  32. */
  33. V get( long timeout, TimeUnit unit )
  34. throws InterruptedException, ExecutionException, TimeoutException;
  35. }

二、线程池之固定线程池newFixedThreadPool

  创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。Executors.newFixedThreadPool(10)的实现如下:

  1. public static ExecutorService newFixedThreadPool( int nThreads )
  2. {
  3. return(new ThreadPoolExecutor( nThreads, nThreads,
  4. 0L, TimeUnit.MILLISECONDS,
  5. new LinkedBlockingQueue<Runnable>() ) );
  6. }

  nThreads :是固定线程数,在了解newFixedThreadPool之前我们先了解一下ThreadPoolExecutor,ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程调度,线程池管理等等服务;Executors方法提供的线程服务,都是通过参数设置来实现不同的线程池机制。ThreadPoolExecutor的构造方法如下:

  1. public ThreadPoolExecutor( int corePoolSize,
  2. int maximumPoolSize,
  3. long keepAliveTime,
  4. TimeUnit unit,
  5. BlockingQueue<Runnable> workQueue )
  6. {
  7. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
  8. Executors.defaultThreadFactory(), defaultHandler);
  9. }
  1. public ThreadPoolExecutor( int corePoolSize,
  2. int maximumPoolSize,
  3. long keepAliveTime,
  4. TimeUnit unit,
  5. BlockingQueue<Runnable> workQueue,
  6. ThreadFactory threadFactory,
  7. RejectedExecutionHandler handler )
  8. {
  9. if ( corePoolSize < 0 ||
  10. maximumPoolSize <= 0 ||
  11. maximumPoolSize < corePoolSize ||
  12. keepAliveTime < 0 )
  13. throw new IllegalArgumentException();
  14. if ( workQueue == null || threadFactory == null || handler == null )
  15. throw new NullPointerException();
  16. this.corePoolSize = corePoolSize;
  17. this.maximumPoolSize = maximumPoolSize;
  18. this.workQueue = workQueue;
  19. this.keepAliveTime = unit.toNanos( keepAliveTime );
  20. this.threadFactory = threadFactory;
  21. this.handler = handler;
  22. }

ThreadPoolExecutor构造方法参数讲解:

ThreadPoolExecutor构造方法参数
参数名 作用
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间
TimeUnit keepAliveTime时间单位
workQueue 阻塞任务队列
threadFactory 新建线程工厂
RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理

  这样我们在回过头来看newFixedThreadPool的实现,核心线程池大小和最大线程池大小都是传入进去的数字,keepAliveTime为0,时间单位为TimeUnit.MILLISECONDS毫秒,对列为LinkedBlockingQueue,线程池工厂为默认,RejectedExecutionHandler为默认。这样我们就知道newFixedThreadPool的代码实现了。关于ThreadPoolExecutor自己的构建请自行了解。
三、实际应用

  1. package com.roc.thread;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.concurrent.Callable;
  6. import java.util.concurrent.ExecutionException;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;
  10.  
  11. public class FixedThreadPoolTest {
  12. public static void main( String[] args )
  13. {
  14. FixedThreadPoolTest fixedThreadPoolTest = new FixedThreadPoolTest();
  15. fixedThreadPoolTest.execut();
  16. }
  17.  
  18. private void execut()
  19. {
  20. ExecutorService executorService = Executors.newFixedThreadPool( 10 );/* 创建为10个线程的固定线程池 */
  21. List<Integer> datas = new ArrayList<Integer>( 100 );
  22. List<Future<Integer> > results = new ArrayList<Future<Integer> >();
  23. int count = 0;
  24. for ( int i = 0; i < 100; i++ )/* 实际项目中数据可以查数据库或者文件,这里仅仅表示模拟 */
  25. {
  26. datas.add( i );
  27. }
  28. for ( int i = 0; i < datas.size(); i++ )
  29. {
  30. results.add( executorService.submit( new executTask( datas.get( i ) ) ) );
  31. }
  32. try {
  33. for ( Future<Integer> future : results )
  34. {
  35. count += future.get();
  36. }
  37. } catch ( InterruptedException e ) {
  38. /* TODO Auto-generated catch block */
  39. e.printStackTrace();
  40. } catch ( ExecutionException e ) {
  41. /* TODO Auto-generated catch block */
  42. e.printStackTrace();
  43. }
  44. System.out.println( Thread.currentThread() + "处理数据总数:" + count );
  45. }
  46.  
  47. class executTask implements Callable<Integer> {
  48. private int data;
  49.  
  50. public executTask( int data )
  51. {
  52. this.data = data;
  53. }
  54.  
  55. @Override
  56. public Integer call() throws Exception
  57. {
  58. try {
  59. System.out.println( Thread.currentThread() + "处理完数据:" + data ); /* 实际项目中这里可以处理业务逻辑 */
  60. } catch ( Exception e ) {
  61. return(-1);
  62. }
  63. return(1);
  64. }
  65. }
  66. }

结果:

Thread[pool-1-thread-10,5,main]处理完数据:9
Thread[pool-1-thread-4,5,main]处理完数据:97
Thread[pool-1-thread-9,5,main]处理完数据:95
Thread[pool-1-thread-3,5,main]处理完数据:96
Thread[pool-1-thread-7,5,main]处理完数据:94
Thread[pool-1-thread-4,5,main]处理完数据:98
Thread[pool-1-thread-5,5,main]处理完数据:99
Thread[main,5,main]处理数据总数:100

Callable+Future+newFixedThreadPool的应用的更多相关文章

  1. Java Callable Future Example(java 关于Callable,Future的例子)

    Home » Java » Java Callable Future Example Java Callable Future Example April 3, 2018 by Pankaj 25 C ...

  2. Java线程池(Callable+Future模式)

    转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...

  3. Java 并发编程——Callable+Future+FutureTask

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  4. 12 Callable & Future & FutureTask

    创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就必须通过共享变量或者使用 ...

  5. java 并发runable,callable,future,futureTask

    转载自:http://www.cnblogs.com/dolphin0520/p/3949310.html package future_call; import java.util.concurre ...

  6. Java并发编程:ThreadPoolExecutor + Callable + Future(FutureTask) 探知线程的执行状况

    如题 (总结要点) 使用ThreadPoolExecutor来创建线程,使用Callable + Future 来执行并探知线程执行情况: V get (long timeout, TimeUnit ...

  7. Java Concurrency - Callable & Future

    One of the advantages of the Executor framework is that you can run concurrent tasks that return a r ...

  8. Java线程池 / Executor / Callable / Future

    为什么需要线程池?   每次都要new一个thread,开销大,性能差:不能统一管理:功能少(没有定时执行.中断等).   使用线程池的好处是,可重用,可管理.   Executor     4种线程 ...

  9. java并发编程-Executor框架 + Callable + Future

    from: https://www.cnblogs.com/shipengzhi/articles/2067154.html import java.util.concurrent.*; public ...

随机推荐

  1. mooc上学习acllib后写的包含背景音乐的小涂鸦板(初入江湖,大佬勿喷)

    #include "acllib.h"ACL_Sound sound1;ACL_Image img;//开始图ACL_Image img1;//涂鸦图ACL_Color c=RED ...

  2. Oozie时bin/oozied.sh start或bin/oozied.sh run出现Bootstrap进程无法启动,http://bigdatamaster:11000/oozie界面也无法打开?E0103: Could not load service classes, java.lang.ClassNotFoundException: Class org.apache.oozie.ser

    不多说,直接上干货! 问题详情 [hadoop@bigdatamaster oozie--cdh5.5.4]$ bin/oozied.sh start Setting OOZIE_HOME: /hom ...

  3. simpleImageTool又纯java图片水印、缩放工具

    simpleImageTool又一个简单.好用的图片格式转换.缩放水印叠加等功能的纯Java图片工具库. simpleImageTool的由来,近期需要用到图片处理,通过网上的图片流直接进行缩放水印叠 ...

  4. 提交到APPStore出现ERROR ITMS-90474

    解决的方案是:在工程的targets--->General----->Develoment Info ------->Status BarStyle

  5. HDU 6035---Colorful Tree(树形DP)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  6. 【EntityFramework 6.1.3】个人理解与问题记录

    前言 又是一个炎热夏日的晚上,开着空调听着音乐又开始了我们今天的博文.此文并不是ROM工具哪家强之类的引战贴,只是本文自己的一点看法和见解,望前辈看官有望斧正 声明 本文欢迎转载,原文地址:http: ...

  7. CrashMonkey4Android 的安装及使用

    CrashMonkey4Android 的安装及使用 简介 CrashMonkey4Android,是一个依靠Cts框架,对原生Monkey进行改造后的产物,拥有以下新增功能: 保存每一步的截图 保存 ...

  8. storm从入门到放弃(一),storm介绍

    背景:目前就职于国内最大的IT咨询公司,恰巧又是毕业季,所在部门招了100多个应届毕业生,本人要跟部门新人进行为期一个月的大数据入职培训,特此将整理的文档分享出来. 原文和作者一起讨论:http:// ...

  9. Nlpir Parser智能语义平台全文搜索

    全文索引用于处理大文本集合,利用它人们可以在海量文本中快速获取需要的信息.全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统.一般来说,全文检索需要具备建立索引和提供查询的基本功能 ...

  10. Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

    我用String代替了链表显示,本题的大意是每k个进行逆序处理,剩下的不够k个的就按照原顺序保留下来. public class ReverseNodes { public static void m ...