我设计过数据库,也写过很多业务代码。我们设计数据库的时候,一般都是外键关联,每次需要外键涉及到的表的属性,都是直接关联查询或者用到的时候再去查询。原来没有分库分表,一个sql搞定。现在分库分表之后,发现每次都得二次查询。这样就需要针对查询出来的list再重新封装一次。
我们大家很熟悉的,都不用思考的就是这样写,至少我从来没测试过这样写的效率,
for(int i = 0;i<userInfoList.size;i++) { //for(UserInfo eachUserInfo:userInfoList) UserInfo eachUserInfo = userInfoList.get(i); UserInfoView userInfoView = new UserInfoView(); userInfoView.setId(eachUserInfo.getId()); userInfoView.setName(eachUserInfo.getName()); userInfoView.setCarId(eachUserInfo.getCarId()); userInfoView.setCarDesc(userInfoDao.queryCar(eachUserInfo.getCarId())); userInfoViewList.add(userInfoView); });
今天看到一篇文章,让我大开眼界。于是测试了几种方法,发现效率真的很有差别。
先说一个线程执行到底,
- for(int i = 0;i<userInfoList.size;i++) {
- for(UserInfo eachUserInfo:userInfoList)
- userInfoList.foreach((eachUserInfo)->{}); //jdk1.8后引入
- userInfoList.stream().map(()->{}).collect(Collectors.toList());//jdk1.8后引入
我用600条数据做的测试,以上几种方式,都是需要3分钟左右。
然后改成多线程执行,
- 用Executors框架
ExecutorService executorService = Executors.newCachedThreadPool(); Future<String> getJobDesc = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { return userInfoDao.queryJob(userInfo.getJobId()); } }); 但是也用了3分钟左右
- 用new Thread(),我是这么理解的,因为不能接受Callable类型的参数,所以借用了FutureTask
FutureTask<String> getJobDesc = new FutureTask<>(new Callable<String>() { @Override public String call() throws Exception { return userInfoDao.queryJob(userInfo.getJobId()); } }); new Thread(getJobDesc).start(); 只用了1分钟。
- 用CompletableFuture,
private Supplier<UserInfoDao> queryUtilsSupplier = UserInfoDao::new;
CompletableFuture<UserInfoDao> getJobDesc = CompletableFuture.supplyAsync(queryUtilsSupplier); getJobDesc.thenAccept(new Consumer<UserInfoDao>() { @Override public void accept(UserInfoDao userInfoDao) { userInfoView.setJobDesc(userInfoDao.queryJob(userInfo.getJobId())); } }); 也用了1分钟左右。
请问我们是否有必要改成FutureTask或者CompletableFuture,还是得考虑一下。