00:00
那接下来我们就来说一下线程串行化,比如在我们的comp future里边,它呢有这么一系列的方法,可以将我们比如AB2个异步任务给它来串联起来,比如我们这个B任务呀,想要等待A任务执行结束以后,拿到A的结果,他才能进行后续的处理,那这就是我们之前的场景,那我们就可以使用这些方法将它们组合起来有序执行,那这样方法呢,我们先来倒着看,首先呢,第一个叫then run。首先呢,我们来看这些run the呢,就是接下来干什么,比如我们呢,A是一个异步任务,这异步任务呢,前提是我们是comp future启动的一步任务,它返回的还是compible future好假设呢,A是一个comp future,这个异步任务它做完了,那它呢就可以调用点Z,那就是接下来继续继续干什么呢?它这有区分,然后呢,Z run就是接下来继续来运行一个异步任务,运行什么异步任务,我们可以传一个runable,并且呢,我们也可以来指定一个自己的线程池,而我们后边加了asy nc的就跟我们之前说的一样,那接下来z wrong接下来要执行的这个B方法,如果我们加了asy nc,相当于开一个新线程来执行B,如果我们不加async,就是跟A共用一个线程来执行B。
01:30
那我们还有一个叫then accept方法,那我们发现如果A执行完了,我想调用then accept accept呢,翻译过来就叫接受的意思,那我们现在要接受一个任务,那执行这个异步任务,我们如果还想要接收A的这个执行结果,所以我们就应该用then accept,而then run呢,是不需要A的执行结果,所以这一块呢,没有任何能感知到上一步的执行结果的。而我们这个z accept就能感知到上一步的执行结果,他传一个consumer,这个T,那这个T呢,就是我们上一步的返回结果,我们拿到结果以后呢,再来执行干什么事情,同样加了asy nc的,那就是跟A共用一个线程来执行我们这个异步任务,那不加asy nc的,那就是开启一个线程,哎,我们刚好说反了,不加的是共用,加的呢,是开启新的,那当然也可以传入自己的线程池对象,它们的写法呢都一样,理解一个就行了。那接下再来看一个叫z of apply,那我们发现呢,前两个这个呢是不接收A的返回值,那么这个AB2个方法,如果我们不想要用A的返回值,直接A执行完了执行B,那么就可以使用这种方式,那如果我们想要A的返回值A执行完了,拿A的返回值B呢,还要再处理,那么就用这个方法,当然呢,还有一种情况,我们呢,拿到了A的返回值,处理了以后。
02:59
我们处理的结果还要返回让别人感知,那么就应该用这个z of来,因为我们发现这一块呢,会有我们这个带泛型的返回值,所以呢,我们这一块有两个泛型,一个是T,一个是U,一个呢就是来接收我们上一步的结果,一个是把我们的返回值再返回出去,这就是我们说的线程串行化,那么就来测试一下。
03:23
那我们还是我们之前的这个方法,我把这一块呢,先来注掉注掉,我把我们的这个计算,我还是拿过来,我来CTRLC,因为我们呢,现在要串联多个线程,好,我们就把我们这多个呢来构建上两个。这是我们的第一个future,把它代码格式化一下,我们就叫future,一我们想要获取结果呢?那就是1GET,我们把这一块都先不要,好,都先不要了,然后呢,如果第一个任务干完了,那接下来干第二个任务,所以呢,我们就可以点一个z.then then什么,如果我们使用then run,那就是我们直接来执行第二个任务,包括我们都来使用后边这个,我们指定我们自己的线程池,好,那我们第二个任务想要干什么活啊,比如我们就在控制台输出。
04:20
那么这个任务二启动了,好,然后呢,我们再来传入我们的这个线程池,那最终呢,它就会返回一个结果啊,我们把这一块去掉,因为呢,我们这个任务一是有返回值的,但任务二呢,执行完没返回值,所以呢,最后一次执行完相当于没返回值,那就是它我们使用Z让as v nc我们来测试一下。好,我们发现呢,一切运行成功,我们这个任务二呢也启动了没问题,但是呢,如果我们用Z状就不能感知我们这个上一步的执行结果,好我们拿过来我们来说一下,那这个串行化线程串行化。
05:04
串行化的第一种方式。我们的这个症状。Z run,什么什么什么,他呢,不能不能获取到上一步的执行结果,那如果我们想要获取到上一步的执行结果来执行好,我把这一块呢,我来删掉,我们来放在我们这儿,我们想要获取我们上一步的执行结果,那么就可以来继续来编写,我们把这个呢改造一下,编写成什么呢?我们使用来有一个叫then accept accept就叫接收的意思,那我们可以来接收我们上一步的结果。所以呢,它里边会传一个我们叫consumer这个东西,我们点过来,我发现呢,它是这么一个对象,但是它没返回值,来看一下,有就说呢,我们如果用这个then accept,那它呢是能接收我们上一步的结果,但是呢不能改变返回值,好就是我们呢无返回能接收上一步结果,但是无返回值,无返回值那我们这个自行状也是一样,这个是无返回值,那么就来写,既然呢是这个样子,那么就来写,我们会接收一个参数,这个参数呢就是结果,那我们就叫result res,然后呢,我们想要执行我们一个任务,我们就来箭头函数,把我们的任务直接写里边,好我们呢来执行一下,比如我们也叫任务二启动了,我们还是放在我们自己的线程池里边,让它来继续执行。
06:34
为了验证我们能用到上一次的结果,我们可以把这个上一次结果来打印一下,好,我们来启动运行。好,我们发现呢,我们这一块呢,也是正常的,我们这个任务二启动,而且呢,能用到我们上一次的结果,这是我们说的then accept ethnic。那接下来我们还有另外一种方式,好完了这个呢也去掉,这是我们上一步的结果,我们返回一个I,然后呢,我们还可以使用有一个叫Z。
07:07
我们使用the apply accept呢,只是能接收到我们上一个的返回值,我们处理,但是呢,我们这次的异步任务还要有返回值供别人来使用,我们就可以使用z apply方法,我们还是使用第二个,我们使用自己的线程池来执行,那这个z apply,那就是既能感知到上一步的结果,又能有返回值,这个能接收上一步的结果,而且呢,还是有返回值。我们来看一下它的这个用法,好,我们还是先把ex放进来,这是我们的线程池,然后呢,我们来执行一个一步任务,来点进来,它接收我们这个方式,这个方式呢,有一个T,有一个R。把这个拿过来,在这儿来给大家看一下,我们apply呢,就是有T有R,相当于有返回值,那么这个T呢,就是上一步的结果了,Res,我们拿过来,上一步结果可以看到,然后呢,我们还要有返回值,比如呢,我们现在这个返回值,我们来给它改变一下,我们来打印。
08:11
首先呢,任务二启动了,我们能看到这个任务二启动了,上一步用的结果呢是res,而我们最终的返回值呢,还给它拼上一个字符串,比如我们就来拼一个hello,再来加上一个res,这是我们对这次的处理,当然我们对这次的处理呢,我们还想有返回结果要让别人用,所以呢,我们这个z apply就有返回值,那返回值呢,我们拿过来走,最终我们返回的这个future就是有返回值的,这个返回值以我们the apply最后一次的这个操作为准,所以它是一个string类型,所以们接下来future想要用这个返回值,我们就直接在这future.get我就能拿到返回值。而且呢,我们一直说这个get,这个get呢,就是一个阻塞方法,比如我们上边呢,执行的非常慢,花了十几秒,那么这个get呢,十几秒以后就会拿到值,我们这个控制台打印就会一直停在这儿,等到拿到值了才会打印。
09:11
那么现在来测试一下。我们最终获取到结果走。哎,那我们发现呢,任务二既启动了,而且我们最终的结果呢,是任务一任务二合起来拼过来的值,那在这呢也能获取到。
我来说两句