Callable和Future
Callable接口类似于Runnable,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到。
先说一个场景,比如,我需要两个字符串,这两个字符串都需要通过请求获取。我们一般的操作是,起一个异步线程,在异步线程中做两次请求,获取两个字符串,并进行处理。假设一次请求的时间是1s,那么处理两个字符串的时间就是2s。那如果我需要多次请求的结果呢,比如100次,那么就需要100s,这显然不太合理。
这时候就可以使用Callable与FutureTask进行配合,启动100个线程(当然启动100个线程也不合理,这里只是假设,正常情况交给设定线程数的线程池处理)。你可能会说,这样线程就不同步了,你怎么知道,第一个线程结束后,第二个线程肯定结束了,可能出了意外,没有返回呢,没关系,这就是Callable+Future的用处。
好了下面说一下用法:
首先我会写模拟两个网络请求(真实网络不可控,就写个方法假设进行了网络请求吧):
图片.png
为了方便对比,我就不设置100次了,就按照十次算就好了:
图片.png
我做了个计时操作,看一下耗时。
FutureTask的用法与Future类似,这里也上一个例子:
图片.png
结果对比
为了做出对比,我再写一个如果按顺序进行网络请求的例子。
[图片上传失败...(image-4972fa-1524713409936)]
好的,我们运行一下看看结果:
图片.png
结果已经很明显了,顺序执行的当然要慢于并发执行。同时使用Callable还解决了并发执行时间不好控制的问题。
这是为什么呢?
为什么每次调用future.get()正好网络请求会完成呢,如果没完成怎么办。
答,会等待,当我们利用future获取callable的返回结果时,如果get不到,还没有完成,会处于等待的状态,等拿到结果再调用下一个future的get,如果耗时差不多,一般也都完了,没完的就会再等。由于是并发执行,所以最终耗时与线程耗时最长的一样。
掌握这种方法对于多线程处理,又想进行一定的控制,有很好的疗效。
不知道你在你的代码中用过没有?
网友评论