JAVA并行异步编程线程池+FutureTask

java 在JDK1.5中引入一个新的并发包java.util.concurrent 该包专门为java处理并发而书写。

在java中熟悉的使用多线程的方式为两种?继续Thread类,实现Runnale。两种方式简单方便。

在Jdk1.5之后其实有第三种方式实现方式,采用并发包中的Callable接口 FuruteTask类 以及ExecutorService接口。

 

说新的实现方式之前先来说讨论一下传统的java执行过程

 

首先一个简单的程序一个方法生成随机数,在生成随机数的方法执行中,睡眠1s模拟方法调用时候的耗时,把结果放进集合中,最后算到总结果。

Java代码   收藏代码
  1. public   
  2.         class Count{  
  3.                 public static void main(String[] args) throws InterruptedException {  
  4.                         long start = System.currentTimeMillis();  
  5.                        Count count = new Count();  
  6.                        List<Integer> res = new ArrayList<>();  
  7.                        res.add(count.random());  
  8.                        res.add(count.random());  
  9.                        res.add(count.random());  
  10.                        res.add(count.random());  
  11.                        int totle =0;  
  12.                        for (int i = 0; i < res.size(); i++) {  
  13.                                totle+=res.get(i);  
  14.                        }  
  15.                       long end = System.currentTimeMillis();  
  16.                        System.out.println("运算结束 耗时:"+(end-start)+"ms  totle:"+totle );  
  17.                        System.out.println("退出main线程!");  
  18.                }  
  19.                 int random() throws InterruptedException{  
  20.                         Thread.sleep(1000); //  
  21.                         return new Random().nextInt(100);  
  22.                 }  
  23.         }  

    结果如下

Java代码   收藏代码
  1. 运算结束 耗时:4000ms  totle:66  
  2. 退出main线程!  

     在传统的编写中是单线程的操作,串行操作,当调用方法count.random(),main线程被阻塞起来,直到睡眠时间到达,自动唤醒main线程。

http://dl2.iteye.com/upload/attachment/0098/3095/cc443846-46c3-338b-aa03-27b649c510ca.png

java为我们提供了多线程机制,利用多线程我们可以实现方法的并行运算,实现多线程的办法,实现Runnable接口重新run,继承Thread 重写run;因为run方法的并没有返回值,我们手动的去创建大量的线程并且维护线程是件很讨厌的事情,并且创建线程也是非常耗费资源的操作,能不能有一个池子来帮我们管理线程呢?有没有一个类能够透明的去进行透明并发的异步操作呢?这个在JDK1.5之前是没有的,在1,5之后出现了一个新包,专门为并发而开发的包,使用并发包中提供的类和接口,将很轻易的实现。并发编程。

Java代码   收藏代码
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. import java.util.Random;  
  4. import java.util.concurrent.Callable;  
  5. import java.util.concurrent.ExecutionException;  
  6. import java.util.concurrent.ExecutorService;  
  7. import java.util.concurrent.Executors;  
  8. import java.util.concurrent.FutureTask;  
  9.   
  10.  public class TestMain {  
  11.         public static void main(String[] args) throws InterruptedException, ExecutionException {  
  12.                 new  TestMain().exec();  
  13.         }  
  14.         void exec() throws InterruptedException, ExecutionException{  
  15.                 //进行异步任务列表  
  16.                 List<FutureTask<Integer>> futureTasks = new ArrayList<FutureTask<Integer>>();  
  17.                 //线程池 初始化十个线程 和JDBC连接池是一个意思 实现重用   
  18.                 ExecutorService executorService = Executors.newFixedThreadPool(10);  
  19.                 long start = System.currentTimeMillis();  
  20.                 //类似与run方法的实现 Callable是一个接口,在call中手写逻辑代码  
  21.                 Callable<Integer> callable = new Callable<Integer>() {  
  22.                         @Override  
  23.                         public Integer call() throws Exception {  
  24.                                 Integer res = new Random().nextInt(100);  
  25.                                 Thread.sleep(1000);  
  26.                                 System.out.println("任务执行:获取到结果 :"+res);  
  27.                                 return  res;  
  28.                         }  
  29.                 };  
  30.                   
  31.                 for(int i=0;i<10;i++){  
  32.                         //创建一个异步任务  
  33.                         FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);  
  34.                         futureTasks.add(futureTask);  
  35.                         //提交异步任务到线程池,让线程池管理任务 特爽把。  
  36.                                //由于是异步并行任务,所以这里并不会阻塞  
  37.                         executorService.submit(futureTask);   
  38.                 }  
  39.                   
  40.                 int count = 0;  
  41.              for (FutureTask<Integer> futureTask : futureTasks) {  
  42.                      //futureTask.get() 得到我们想要的结果   
  43.                      //该方法有一个重载get(long timeout, TimeUnit unit) 第一个参数为最大等待时间,第二个为时间的单位  
  44.                      count+= futureTask.get();  
  45.         }  
  46.            long end = System.currentTimeMillis();  
  47.            System.out.println("线程池的任务全部完成:结果为:"+count+",main线程关闭,进行线程的清理");  
  48.            System.out.println("使用时间:"+(end-start)+"ms");  
  49.            //清理线程池   
  50.            executorService.shutdown();  
  51.                   
  52.         }  
  53. }  

 上述情况如果不用异步并行,程序将至少睡眠10s

 使用之后的结果

Java代码   收藏代码
  1. 任务执行:获取到结果 :99  
  2. 任务执行:获取到结果 :78  
  3. 任务执行:获取到结果 :52  
  4. 任务执行:获取到结果 :78  
  5. 任务执行:获取到结果 :97  
  6. 任务执行:获取到结果 :8  
  7. 任务执行:获取到结果 :97  
  8. 任务执行:获取到结果 :3  
  9. 任务执行:获取到结果 :78  
  10. 任务执行:获取到结果 :31  
  11. 线程池的任务全部完成:结果为:621,main线程关闭,进行线程的清理  
  12. 使用时间:<span style="color: #ff0000;"><span style="color: #000000;">1004ms</span> </span>  

   我们试着把线程池的大小减少一半

  

Java代码   收藏代码
  1. 任务执行:获取到结果 :87  
  2. 任务执行:获取到结果 :60  
  3. 任务执行:获取到结果 :13  
  4. 任务执行:获取到结果 :18  
  5. 任务执行:获取到结果 :8  
  6. 任务执行:获取到结果 :86  
  7. 任务执行:获取到结果 :52  
  8. 任务执行:获取到结果 :4  
  9. 任务执行:获取到结果 :23  
  10. 任务执行:获取到结果 :16  
  11. 线程池的任务全部完成:结果为:367,main线程关闭,进行线程的清理  
  12. 使用时间:<span style="color: #000000;">2017ms  
  13. </span>  

   好玩吧 时间延长了一半。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值