FutureTask和CompletableFuture的模拟使用

 模拟了查询耗时操作,并使用FutureTask和CompletableFuture分别获取计算结果,统计执行时长

package org.alllearn.futurtask;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

public class CompletableFutureTest {
    public static void main(String[] args) {

        CompletableFutureTest test = new CompletableFutureTest();
        List<User> users = test.getUsers();
        //流计算的简单使用
        Stopwatch started = Stopwatch.createStarted();
        double average = users.stream().mapToInt(User::getAge).average().getAsDouble();
        System.out.println(average + "  " + started.elapsed());

        //模拟通过id集合去其他表批量查询数据
        //单线程任务分割,数据库承受不了大量id的in查询
        List<List<User>> partition1 = Lists.partition(users, users.size() / 200);
        started.reset();
        started.start();
        double average1 = partition1.stream().mapToDouble(test::select).average().getAsDouble();
        System.out.println(average1 + "  " + started.elapsed());


        //多线程任务两种方案FutureTask、CompletableFuture
        int cpu = Runtime.getRuntime().availableProcessors();
        //计算密集型cpu+1,io密集型cpu*2
        ForkJoinPool forkJoinPool = new ForkJoinPool(cpu + 1);
        List<List<User>> partition2 = Lists.partition(users, users.size() / 200);


        //FutureTask
        started.reset();
        started.start();
        double average2 = partition2.stream()
                .map(u -> {
                    FutureTask<Double> futureTask = new FutureTask<>(() -> test.select(u));
                    forkJoinPool.submit(futureTask);
                    return futureTask;
                })
                .collect(Collectors.toList())
                .stream().
                mapToDouble(f -> {
                    try {
                        return f.get();
                    } catch (InterruptedException | ExecutionException e) {
                        throw new RuntimeException(e);
                    }
                })
                .average()
                .getAsDouble();
        System.out.println(average2 + "  " + started.elapsed());

        //CompletableFuture
        started.reset();
        started.start();
        double average3 = partition2.stream()
                .map(u -> CompletableFuture.supplyAsync(() -> test.select(u), forkJoinPool))
                .collect(Collectors.toList())
                .stream().
                mapToDouble(CompletableFuture::join)
                .average()
                .getAsDouble();
        forkJoinPool.shutdown();
        System.out.println(average3 + "  " + started.elapsed());
    }

    //模拟查询耗时
    public Double select(List<User> user) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return 1D;
        //return Math.random();
    }

    //模拟获取用户
    public List<User> getUsers() {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 20000; i++) {
            users.add(new User(i, "user" + i, 1));
        }
        return users;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    static class User {
        private int id;
        private String name;
        private int age;
    }

}


运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FutureTaskCompletableFuture都是用于异步获取线程执行结果的工具。 FutureTask实现了Future接口,并且还实现了Runnable接口,所以可以直接将FutureTask提交到线程池执行,并且可以获取执行结果。而Future只支持获取Callable的执行结果。所以从功能上来说,FutureTask更加全面且方便。FutureTask的底层是基于AQS(AbstractQueuedSynchronizer)实现的。 为了满足对异步编程的需求,JDK8引入了CompletableFutureCompletableFuture是在JDK1.8之后出现的,与之前的FutureFutureTask有很大的区别。CompletableFuture的功能更加强大且复杂,融入了大量的流式编程思想。可以等待多个CompletableFuture对应的计算结果都出来后再做一些操作。 总结来说,FutureTaskCompletableFuture都是用于异步获取线程执行结果的工具,但是CompletableFuture的功能更加丰富和灵活。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [FutureFutureTaskCompletableFuture](https://blog.csdn.net/XH413235699/article/details/97302732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [【异步编程学习笔记】JDK中的FutureTaskCompletableFuture详解(使用示例、源码)](https://blog.csdn.net/qq_41358574/article/details/120521955)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值