一个CompletableFuture的例子

这是一个查询多个商店相同商品价格的例子,我会使用CompletableFuture的基础方法:

1.CompletableFuture.supplyAsync() : 异步获取方法返回值。

2.CompletableFuture.thenApply():将异步获取的返回值作为参数处理。
3.CompletableFuture.thenCompose():将上一个异步方法的返回值作为第二个异步方法的参数。
 
示例代码:
 
 
package ShopCompletableFuture;

import org.apache.commons.lang3.RandomUtils;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * Created by ibm on 2017/5/3.
 */
public class ShopExercise {

    public static void main(String[] args) {
        long st = System.nanoTime();
        ShopExercise shopExercise = new ShopExercise();
        shopExercise.getPrices("xiaozhen");
        long et = System.nanoTime();
        System.out.println("耗时: " + (et -st)/1000_1000 + "ms");
    }

    /**
     * 配置一个线程池的执行器,其中线程的数量等于查询的个数,然后设置为守护线程(不会阻止程序退出)
     * 为什么使用线程池:因为开启的线程过多,返回会造成查询缓慢
     */
    final Executor executor = Executors.newFixedThreadPool(10, (Runnable r) -> {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    });

    /**
     * 查询某个商品在每个商店的价格
     */
    public List<Double> getPrices(String product){
        //初始化商店列表
        List<String> shops = Arrays.asList("A_SHOP","B_SHOP","C_SHOP","D_SHOP","E_SHOP");
        //并行查询 + 异步请求
        List<CompletableFuture<Double>> futures = shops
                .parallelStream()
                .map(s -> CompletableFuture.supplyAsync(() -> getPrice(product,s),executor))
                .map(future -> future.thenApply(Quote::parse))
                .map(future -> future.thenCompose(quote ->
                    CompletableFuture.supplyAsync(() -> DiscountService.apply(quote),executor)
                ))
                .collect(Collectors.toList());
        return futures.stream().map(CompletableFuture::join).collect(Collectors.toList());

        //=====下面的方式:在同一个stream中进行两次map操作:查询会顺序执行,因为流水线操作是顺序执行同步的====
        //return shops.parallelStream().map(s -> CompletableFuture.supplyAsync(() -> {
        //    StringBuilder result = new StringBuilder(s);
        //    result.append(" : " + getPrice(product));
        //    return result.toString();
        //}))
        //.map(CompletableFuture::join)
        //.collect(Collectors.toList());
    }
    /**
     * 同步获取价格
     */
    public String getPrice(String product,String shopName){
        double price = calculatePrice(product);
        Discount discount = Discount.CLOD;
        String result = String.format("\n%s:%s:%s:%s:%s",shopName,product,price + "",discount.value + "",discount.desc);
        System.out.println(result);
        return result;
    }
    /**
     * 计算价格:耗时查询 + 随机价格
     * @param product 商品名称
     * @return 随机价格
     */
    private double calculatePrice(String product){
        delay();
        return RandomUtils.nextDouble(10,100);
    }
    /**
     * 制造耗时查询
     */
    private void delay(){
        try {
            Thread.sleep(2000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 折扣
     */
    enum Discount{

        NONE(1,"没优惠"),
        SILVER(0.7f,"七折"),
        CLOD(0.5f,"五折"),
        DIAMOND(0.3f,"三折");

        double value;
        String desc;

         Discount(double value,String desc){
            this.value = value;
            this.desc = desc;
        }
    }
//=============================================================
    /**
     * 异步获取价格
     */
    public Future<Double> getPriceAsync(String product){
        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
        //在另一个线程中计算价格,当计算完成过后,将price赋值给future对象
        new Thread(() -> {
            try{
                double price = calculatePrice(product);
                futurePrice.complete(price);
            }catch (Exception e){
                //如果有异常,抛出去避免主线永久程阻塞
                futurePrice.completeExceptionally(e);
            }
        }).start();
        //使用supplyAsync工厂方法,两种方式完全等效
        //CompletableFuture<Double> futurePrice2 = CompletableFuture.supplyAsync(() -> calculatePrice(product));
        return futurePrice;
    }
}
package ShopCompletableFuture;

/**
 * Created by ibm on 2017/5/8.
 */
public class DiscountService {

    public static double apply(Quote quote) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String sout = String.format("\n【折后 :%s:%s:%s:%s:%s",quote.shopName,quote.product,quote.price * quote.discountValue,quote.discountValue + "",quote.discountDesc);
        System.out.println(sout);
        return quote.price * quote.discountValue;
    }

}

 
package ShopCompletableFuture;

/**
 * Created by ibm on 2017/5/8.
 */
public  class Quote{
    String shopName;
    String product;
    double price;
    double discountValue;
    String discountDesc;

    static Quote parse(String s){
        String[] split = s.split(":");
        Quote quote = new Quote();
        quote.shopName = split[0];
        quote.product = split[1];
        quote.price = Double.valueOf(split[2]);
        quote.discountValue = Double.valueOf(split[3]);
        quote.discountDesc = split[4];
        return quote;
    }
}

 
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值