CompletableFuture相关测试源码, 可以看出返回一个Future对象作为钩子,就能够使得耗时的方法不再堵塞进程。
public class CompletableFutureShop {
Random random =new Random();
public double getPrice(String product) {
return calculatePrice(product);
}
public void delay() {
try {
//模拟耗时操作
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private double calculatePrice(String product) {
delay();
//模拟价格计算
return random.nextDouble()* product.charAt(0)+product.charAt(1);
}
public Future<Double> getPriceAsync(String product){
// 采用 返回一个CompletableFuture的对象的方式,可以让该方法不再堵塞
// 期间可以做一些其他事情,然后再查看返回结果
CompletableFuture<Double> futurePrice= new CompletableFuture();
new Thread(()->{
double price = calculatePrice(product);
futurePrice.complete(price);
}) .start();
return futurePrice;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletableFutureShop shop = new CompletableFutureShop();
System.out.println("Start:"+ LocalDateTime.now());
Future<Double> futureResult= shop.getPriceAsync("BBB");
System.out.println("Finish getPriceAsync :"+ LocalDateTime.now());
Double result= shop.getPrice("AAA");
System.out.println("Finish getPrice :"+ LocalDateTime.now());
System.out.println("Obtain result: "+ LocalDateTime.now()+":"+ result);
System.out.println("Obtain futureResult: "+ LocalDateTime.now()+":"+futureResult.get());
}
}
运行结果:
Start:2017-11-23T13:30:17.898100700
Finish getPriceAsync :2017-11-23T13:30:17.912113500
Finish getPrice :2017-11-23T13:30:20.914173800
Obtain result: 2017-11-23T13:30:20.914173800:127.31344312473337
Obtain futureResult: 2017-11-23T13:30:20.918915600:100.80537734849176
RecursiveTask , ForkJoinTask 调用代码, 这里采用了分而治之的思想
//这实际是JAVA7的新特性
public class ForkJoinSumCalculator extends java.util.concurrent.RecursiveTask<Long> {
private final long[] numbers;
private final int start;
private final int end;
public static final long THRESHOLD=10;
public ForkJoinSumCalculator(long[] numbers) {
this(numbers,0,numbers.length);
}
public ForkJoinSumCalculator(long[] numbers, int start, int end) {
this.numbers=numbers;
this.start= start;
this.end=end;
}
@Override
protected Long compute() {
int length = end-start;
//到达需处理的最小单元,进行计算
if(length<=THRESHOLD) {
return computeSequentially();
}
int splitPoint = start+length/2;
//将任务一分为二,左分支做一半,又分支做一半
ForkJoinSumCalculator leftTask=new ForkJoinSumCalculator(numbers, start, splitPoint);
//将左分支fork出去
leftTask.fork();
ForkJoinSumCalculator rightTask= new ForkJoinSumCalculator(numbers, splitPoint, end);
//右分支也可以fork出去,这里为了节省资源,共用了和父线程公用一个
Long rightResult= rightTask.compute();
//将左分支计算结果返回
Long leftResult= leftTask.join();
return leftResult+rightResult;
}
private long computeSequentially() {
long sum=0;
//求和统计计算
for(int i=start;i<end;i++) {
sum+=numbers[i];
}
return sum;
}
public static long forkJoinSum(long n) {
// 生成一个顺序数组
long[] numbers= LongStream.rangeClosed(1, n).toArray();
// 利用ForkJoinPool线程池去调用Task
ForkJoinTask<Long> task = new ForkJoinSumCalculator(numbers);
return new ForkJoinPool().invoke(task);
}
public static void main(String[] args) {
Long result= forkJoinSum(100);
System.out.println(result);
Long result2= forkJoinSum(1000);
System.out.println(result2);
Long result3= forkJoinSum(10000);
System.out.println(result3);
}
}
运行结果:
5050
500500
50005000