Java8 CompletableFuture(1)创建线程 supplyAsync runAsync

一、前言

Java8推出了CompletableFuture,它实现了很多功能,用它编写的代码也比较优雅。

目前大多数公司用的JDK已经从6升级到8及以上了,那么作为一名合格的Java打工人,除了要掌握之前的FutureTask和CompletionService,也要掌握CompletableFuture。

否则你在项目中不用Lambda,也不用CompletableFuture,那你JDK升级到8,升个寂寞?

二、CompletableFuture创建新线程

CompletableFuture,默认依靠fork/join框架启动新的线程实现异步与并发的。

它提供了函数式编程的能力,可以通过回调函数的方式处理返回结果,并且提供了转换和组合CompletableFuture的方法。

在用CompletableFuture之前,我认为得先熟悉下Java8的Lambda编程语法,《Java8实战》这本书非常适合阅读。

CompletableFuture创建线程有2种方式:supplyAsync(有返回值)和:runAsync(无返回值)

1. 创建测试用的业务类

创建一个DeptService,模拟根据Id获取部门的方法getById(Integer id)。

public class DeptService {

    public Dept getById(Integer id)  {

        System.out.println("线程:" + Thread.currentThread().getName() + " getById(" + id + ")");

        if (id == 1){
            return new Dept(1, "研发一部");
        } else if (id == 2){
            return new Dept(2, "研发二部");
        } else {
            throw null;
        }
    }
}

创建一个UserService ,模拟getById()和save()这2个方法。

public class UserService {

	//根据Id获取User
    public User getById(Integer id) throws Exception {

        System.out.println("线程:" + Thread.currentThread().getName() + " getById(" + id + ")");

        if (id == 1){
            return new User(1, "冬哥", 31);
        } else if (id == 2){
            return new User(2, "珣爷", 30);
        } else {
            throw new Exception("未能找到人员");
        }
    }

	//保存User
    public User save(User user){
        System.out.println("线程:" + Thread.currentThread().getName() + " save()," + user.toString());
        return user;
    }
}

2. supplyAsync(有返回值)

supplyAsync有2种,第二个需要多传1个线程池的实现。

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor)

需求:

  • 在main线程里创建一个线程异步获取id=1的部门
  • 在main线程里获取新线程的返回值

supplyAsync()中调取deptService.getById(1),并return它的值。

public class Thread01_SupplyAsync {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        DeptService deptService = new DeptService();

        CompletableFuture<Dept> deptCompletableFuture = CompletableFuture.supplyAsync(() -> {

            Dept dept = deptService.getById(1);
            return dept;
        });

        System.out.println("线程:" + Thread.currentThread().getName() +
                " 结果:" + deptCompletableFuture.get());
    }
}

运行结果如下,可见DeptService是在新的线程里执行的,而在main主线程中调用get()获取线程的结果会阻塞主线程。

线程:ForkJoinPool.commonPool-worker-1 getById(1)
线程:main 结果:Dept{id=1, name='研发一部'}

3. runAsync(无返回值)

runAsync适用无返回值的情况,也有2种,第二个需要多传1个线程池的实现

public static CompletableFuture<Void> runAsync(Runnable runnable)

public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                   Executor executor)

对上面SupplyAsync的测试代码稍做修改,runAsync()里没有返回值,所以去掉return。

public class Thread02_RunAsync {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        DeptService deptService = new DeptService();

        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {

            deptService.getById(1);
        });

        System.out.println("线程:" + Thread.currentThread().getName() +
                " 结果:" + voidCompletableFuture.get());
    }
}

运行结果如下,可以看出runAsync也是创建了新线程,调用get方法只能返回null。

线程:ForkJoinPool.commonPool-worker-1 getById(1)
线程:main 结果:null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑟 王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值