`
247687009
  • 浏览: 171403 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多

 

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

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

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

 

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

 

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

public 
        class Count{
                public static void main(String[] args) throws InterruptedException {
                        long start = System.currentTimeMillis();
                       Count count = new Count();
                       List<Integer> res = new ArrayList<>();
                       res.add(count.random());
                       res.add(count.random());
                       res.add(count.random());
                       res.add(count.random());
                       int totle =0;
                       for (int i = 0; i < res.size(); i++) {
                               totle+=res.get(i);
                       }
                      long end = System.currentTimeMillis();
                       System.out.println("运算结束 耗时:"+(end-start)+"ms  totle:"+totle );
                       System.out.println("退出main线程!");
               }
                int random() throws InterruptedException{
                        Thread.sleep(1000); //
                        return new Random().nextInt(100);
                }
        }

    结果如下

运算结束 耗时:4000ms  totle:66
退出main线程!

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



 

那么有没有什么办法来减少main主线程的阻塞时间呢?能不能让这几个操作并行进行呢?如果是并行运行带来什么好处呢?

 

并行带来的好处,可以减少比较多的方法执行时间,如random()方法并行计算,也就是说main线程的阻塞只有1s,阻塞时间减少75%


 

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

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

 public class TestMain {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
                new  TestMain().exec();
        }
        void exec() throws InterruptedException, ExecutionException{
                //进行异步任务列表
                List<FutureTask<Integer>> futureTasks = new ArrayList<FutureTask<Integer>>();
                //线程池 初始化十个线程 和JDBC连接池是一个意思 实现重用 
                ExecutorService executorService = Executors.newFixedThreadPool(10);
                long start = System.currentTimeMillis();
                //类似与run方法的实现 Callable是一个接口,在call中手写逻辑代码
                Callable<Integer> callable = new Callable<Integer>() {
                        @Override
                        public Integer call() throws Exception {
                                Integer res = new Random().nextInt(100);
                                Thread.sleep(1000);
                                System.out.println("任务执行:获取到结果 :"+res);
                                return  res;
                        }
                };
                
                for(int i=0;i<10;i++){
                        //创建一个异步任务
                        FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
                        futureTasks.add(futureTask);
                        //提交异步任务到线程池,让线程池管理任务 特爽把。
                               //由于是异步并行任务,所以这里并不会阻塞
                        executorService.submit(futureTask); 
                }
                
                int count = 0;
             for (FutureTask<Integer> futureTask : futureTasks) {
                     //futureTask.get() 得到我们想要的结果 
                     //该方法有一个重载get(long timeout, TimeUnit unit) 第一个参数为最大等待时间,第二个为时间的单位
                     count+= futureTask.get();
        }
           long end = System.currentTimeMillis();
           System.out.println("线程池的任务全部完成:结果为:"+count+",main线程关闭,进行线程的清理");
           System.out.println("使用时间:"+(end-start)+"ms");
           //清理线程池 
           executorService.shutdown();
                
        }
}

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

 使用之后的结果

任务执行:获取到结果 :99
任务执行:获取到结果 :78
任务执行:获取到结果 :52
任务执行:获取到结果 :78
任务执行:获取到结果 :97
任务执行:获取到结果 :8
任务执行:获取到结果 :97
任务执行:获取到结果 :3
任务执行:获取到结果 :78
任务执行:获取到结果 :31
线程池的任务全部完成:结果为:621,main线程关闭,进行线程的清理
使用时间:1004ms 

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

  

任务执行:获取到结果 :87
任务执行:获取到结果 :60
任务执行:获取到结果 :13
任务执行:获取到结果 :18
任务执行:获取到结果 :8
任务执行:获取到结果 :86
任务执行:获取到结果 :52
任务执行:获取到结果 :4
任务执行:获取到结果 :23
任务执行:获取到结果 :16
线程池的任务全部完成:结果为:367,main线程关闭,进行线程的清理
使用时间:2017ms

   好玩吧 时间延长了一半。

 

 

  • 大小: 19.5 KB
  • 大小: 11.4 KB
2
0
分享到:
评论

相关推荐

    Java并发编程实战

    1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性问题 1.3.3 性能问题 1.4 线程无处不在 第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全...

    Java 并发编程实战

    1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性问题 1.3.3 性能问题 1.4 线程无处不在 第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全...

    Java并发编程原理与实战

    Spring对并发的支持:Spring的异步任务.mp4 使用jdk8提供的lambda进行并行计算.mp4 了解多线程所带来的安全风险.mp4 从线程的优先级看饥饿问题.mp4 从Java字节码的角度看线程安全性问题.mp4 synchronized保证线程...

    Java并发编程(学习笔记).xmind

    Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...

    龙果 java并发编程原理实战

    龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...

    龙果java并发编程完整视频

    第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的安全风险00:13:16分钟 | 第12节从线程的优先级看饥饿问题00:18:42...

    Java 并发编程原理与实战视频

    java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...

    java并发编程

    第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的安全风险00:13:16分钟 | 第12节从线程的优先级看饥饿问题00:18:42...

Global site tag (gtag.js) - Google Analytics