CompletableFuture在手,并发不愁!

CompletableFuture是什么?

CompletableFuture是jdk8以来出现的一个专门处理并发的类库,是Future的加强版,集成了更多的方法以应对更加复杂的业务场景。
本节内容需要有一定的函数式编程基础以及lambda表达式基础。
传送门

大家一起找出所有成年人

结合之前业务中的场景,抽象出了这样一个模型,假设从数据库中得到一群人员信息,要筛选出所有成年人。
此时可以将所有的返回结果全部存入一个map中,等待并发结束再去查看所有map中的结果。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;


public class CompletableFutureTest {
    public static void main(String[] args) {
        ArrayList<Person> persons = new ArrayList<Person>();
        persons.add(new Person("小明", 18));
        persons.add(new Person("小华", 17));
        persons.add(new Person("小红", 16));
        persons.add(new Person("大明", 19));
        persons.add(new Person("超明", 20));
        System.out.println(persons);
        //并发找出所有成年人,并存入map中
        ArrayList<CompletableFuture<Boolean>> resList = new ArrayList<CompletableFuture<Boolean>>();
        HashMap<Person, Boolean> map = new HashMap<>();
        for (Person person : persons) {
            resList.add(CompletableFuture.supplyAsync(() -> findMan(person), Executors.newFixedThreadPool(5)).whenComplete((r, e) -> {
                if (null == e) {
                    map.put(person, r);
                } else {
                    System.out.println("执行错误");
                }
            }));
        }
        //从map中获取结果
        CompletableFuture.allOf(resList.toArray(new CompletableFuture[resList.size()])).whenComplete((r, e) -> {
            if (null == e) {
                map.forEach((key,value)->{
                    String msg = value ? (key+"已成年"):(key+"未成年");
                    System.out.println(msg);
                });
            } else {
                System.out.println("执行错误");
            }
        }).join();
    }
	//判断一个人是否成年
    private static boolean findMan(Person person) {
        return person.getAge() >= 18 ? true : false;
    }
}

从传送门中可知,supplyAsync是供给型接口,无需传入参数,有返回值,其他的可以类比,此处的whenComplete则是并发处理完成后异步回调需要做的处理。allOf则是等待所有并发完成,join()和get()方法都是用来获取CompletableFuture异步之后的返回值。join()方法抛出的是uncheck异常(即未经检查的异常),不会强制开发者抛出。get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理。

此时就可以巧妙地通过一个中间map来进行结果传递。

成年认证

此时如果不同的机构对于成年的认证不同,A机构认为大于18岁才能算成年,B机构认为大于等于18岁就算成年。此时又可以对findMan进行封装,可以通过反射获取特定的类进行校验,以SpringBoot工程为例。
此时可以给person加一个属性,认证机构。

@Data
@AllArgsConstructor
public class Person {
    private String name;
    private int age;
    private String department;
}

编写工具类获取SpringApplicationContext

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }
}

定义接口以及实现类

public interface Department {
    boolean findManByDepartment(Person person);
}
@Service
public class A implements Department {
    @Override
    public boolean findManByDepartment(Person person) {
        return person.getAge() > 18 ? true : false;
    }
}
@Service
public class B implements Department{
    @Override
    public boolean findManByDepartment(Person person) {
        return person.getAge() >= 18 ? true : false;
    }
}

通过反射动态返回结果

public class CompletableFutureTest {
    public static void main(String[] args) {
        ArrayList<Person> persons = new ArrayList<Person>();
        persons.add(new Person("小明", 18,"A"));
        persons.add(new Person("小华", 17,"B"));
        persons.add(new Person("小红", 16,"A"));
        persons.add(new Person("大明", 19,"B"));
        persons.add(new Person("超明", 20,"A"));
        System.out.println(persons);
        //并发找出所有成年人,并存入map中
        ArrayList<CompletableFuture<Boolean>> resList = new ArrayList<CompletableFuture<Boolean>>();
        HashMap<Person, Boolean> map = new HashMap<>();
        for (Person person : persons) {
            resList.add(CompletableFuture.supplyAsync(() -> findMan(person), Executors.newFixedThreadPool(5)).whenComplete((r, e) -> {
                if (null == e) {
                    map.put(person, r);
                } else {
                    System.out.println("执行错误");
                }
            }));
        }
        //从map中获取结果
        CompletableFuture.allOf(resList.toArray(new CompletableFuture[resList.size()])).whenComplete((r, e) -> {
            if (null == e) {
                map.forEach((key,value)->{
                    String msg = value ? (key+"已成年"):(key+"未成年");
                    System.out.println(msg);
                });
            } else {
                System.out.println("执行错误");
            }
        }).join();
    }

    private static boolean findMan(Person person){
        boolean flag = false;
        try {
            ApplicationContext applicationContext = SpringContextUtil.getApplicationContext();
            Class<?> clazz = Class.forName(person.getDepartment());
            Method method = clazz.getDeclaredMethod("findManByDepartment", person.getClass());
            flag = (boolean) method.invoke(applicationContext.getBean(clazz), person);
        } catch (Exception e) {
            System.out.println("执行错误");
        }
        return flag;
    }
}

总结

通过以上方法就可以对并发处理进行管控以及结果记录或处理,可以大大的提高系统性能和工作效率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值