java异步并行_JAVA并行异步编程,线程池+FutureTask

在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 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线程。

26e00d13e30a2c872656ba853373493f.png

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

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

e29ecadceaef709dcf151114ffe747fc.png

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> futureTasks = new ArrayList>();

//线程池 初始化十个线程 和JDBC连接池是一个意思 实现重用

ExecutorService executorService = Executors.newFixedThreadPool(10);

long start = System.currentTimeMillis();

//类似与run方法的实现 Callable是一个接口,在call中手写逻辑代码

Callable callable = new Callable() {

@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 futureTask = new FutureTask(callable);

futureTasks.add(futureTask);

//提交异步任务到线程池,让线程池管理任务 特爽把。

//由于是异步并行任务,所以这里并不会阻塞

executorService.submit(futureTask);

}

int count = 0;

for (FutureTask 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

好玩吧 时间延长了一半。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值