Future这玩意

异步执行,听起来很抽象,简单的来说,主线程不管这件事了,起了个新的线程去做这件事,那么这件事的执行过程,对于主线程而言,就是异步的。

可以把这件事的执行过程给抽象出来,定义为一个方法,方法的内容就是这件事的具体执行过程。

比如Runnable。

Runnable

Runnable接口只有一个run()方法,run()里面的内容就是这件事执行的过程,怎么去异步呢?

new Thread(new Runnable(){
		@Override
		public void run() {
				// 这件事的逻辑代码
		}
}.start();

如果主线程去执行上面这段代码,那么这件事的执行对于主线程来说,就是异步执行的。

举个例子,小明吃完了饭,是不是得去洗碗呐,如果小明是单身狗,那洗碗这件事没人帮的了小明,所以小明就得花这10几分钟来洗碗,但小明有钱啊,买个洗碗机,洗碗这件事就不用小明这个主线程来做了,当然是用洗碗机这个新线程去洗碗,洗碗这件事对小明来说就是异步的了。

买的第一代的洗碗机,还有有点low,这洗碗机最后会把碗吃掉,对应于run()不会返回洗完的碗,小明还得看着洗碗机洗碗,不能做其他事情,等于主线程调用了洗碗线程.join()。

如果想洗碗机洗完碗后给碗,可用Callable。但暂时还做不到你不用看着洗碗机洗碗。

Callable

Runnable的run()方法是void,Callable的call()方法,返回的是泛型V,在用法上有着很大的区别,Runnable的实现类实例,可以作为Thread对象的参数,也就是Runnable可以与Thread直接关联,Callable要被Thread执行的话,只能转成Runnable。

是你的话,怎么解决Callable与Thread的关联问题?

那我就写个类,实现Runnable接口,把Callable注入进来,然后run()方法就执行Callable对象的call()方法。

哈哈,其实java提供了Callable与Thread的桥梁,FutureTask就是这么一回事,但是呢FutureTask这名字总感觉是Callable和Runnable关系不大…

Callable<Bowl> washBowl = new Callable<Bowl>(){
		@Override
		public Bowl call() {
				// 洗碗这件事,可能会花10分钟,或者15分钟,这个时间对小明来说透明的
		}
}

// 把washBowl这件事转为Thread可执行的事情,还得需要FutureTask这个中间者
FutureTask<Bowl> washBowlMiddler = new FutureTask<>(washBowl);

// 洗碗机去异步地洗碗
Thread washBowlMachine = new Thread(washBowlMiddler).start();

// 怎么拿到洗干净后的碗呢,有个接口叫Future
Bowl cleanBowls = washBowlMiddler.get();

从上面的例子可以看到,对于Callable的结果V,需要借助FutureTask的get()来获取,Callable也蛮可怜的,什么东西都要这个靠中间者来帮忙…

FutureTask的get()也是一个阻塞的方法,这个方法是FutureTask继承于Future接口的get()方法,所以FutureTask = 实现了Callable + 实现了Runnbale + 实现Future 。到这好像能知道FutureTask这个名字的由来了,首先他包含了要做的事情(Task),还可以拿到异步执行事情的结果(Future)。

所以最后一行代码,主线程会阻塞在那,等于小明还是只能看着洗碗机洗10分钟或者更久,但好处是小明可以拿到洗干净的碗。

那我又想要洗干净的碗,又想不盯着洗碗机,可以躺床上打游戏,那可以用Guava。

Guava

第三代洗碗机终于发布,小明直呼好家伙,直接入手,这下可以不用盯着洗碗机洗完了,还能给出干净的碗。

想想看,为什么小明之前要傻傻的阻塞在那盯着洗碗机把碗洗完?因为小明不知道洗碗机会洗多久,第三代改良后,洗碗机在洗完后,会哔哔哔的叫,这时候小明就知道碗原来洗好了。

在Guava中,有几个组件需要提前去了解下,

  • FutureCallback,这个接口名字里包含callback,大概知道是回调的东西,还带Future,那应该也能知道是异步执行的东西,所以这组件就是异步执行结果的回调,要注意的是,这个结果可能是执行成功的结果,也可能是执行出错的结果,所以FutureCallback有两个方法:

void onSuccess(@Nullable V var1); // 成功的结果,那就传入成功的结果

void onFailure(Throwable var1); // 失败的结果,那就传失败的原因

   说白了,就是做善后处理的接口。
  • ListenableFuture,名字也带有Future,真的和Future过不去了…,姑且就把这个当做是 FutrueTask的加强版,FutureTask执行完后的结果想要执行到上面的FutureCallback善后工作,就得和它关联起来,所以ListenableFuture就由一个addListener(Runnable r, Executor e)方法来进行关联,很明显,这个方法是观察者模式,至于ListenableFuture怎么合FutureCallback如何关联起来,Guava也提供了专门的步骤:
Futures.addCallback(listenableFuture, new FutureCallBack<Bowl>() {
		@override
		public void onSuccess(Bowl cleanBowls) {
				// 洗碗机洗完了,传进来干净的碗
		}

		@Override
		public void onFailure(Throwable t) {
				// 洗碗机故障了,传进来故障的对象
		}
}

可类比下支付的回调。
现在看起来还比较抽象,没事,我也觉得抽象,所以明天再写。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值