多线程之callable详解
发布日期:2022-04-11 08:52:45 浏览次数:11 分类:技术文章

本文共 1679 字,大约阅读时间需要 5 分钟。

多线程之callable详解

面试有人会问:线程的实现方式有几种?
很多人可能回答:2种,继承Thread类,实现Runnable接口。
很多忽略了callable这种方式。
也许有人知道callable,也知道callable和Runnable的区别是callable可以有返回值,也可以抛出异常的特性,而Runnable没有。

这里估计很多人懵逼,接下来我们就从源码层次讲解这个问题。

注意callable可以有返回值,也可以抛出异常这点很关键。

很多时候我们让多线程去帮我们处理事情,是需要拿到返回值的,有了异常也可以处理,比如某宝的APP页面,一个页面展示3个块,而每个块展示的信息从后端获取的接口都不一样,那么是让前端调后端3次接口吗?
肯定不行,后端可以把3个块的信息,包装成一个接口,全部返回,那么问题来了,后端调用3个接口,比如第一个接口需要1秒,第二个需要2秒,第三个需要3秒,那么包装的这个接口响应时间最少6秒,怎么解决这个问题呢,可以用多线程来帮我们解决。
启动3个线程,每个线程去调用一个接口,那么3个线程一共执行完的时间就是最慢的那个线程的执行时间,这样接口的响应时间就变成了3秒,一下节省了一半的时间。
那么问题来了,线程如何把执行的业务代码的结果返回来呢?这时候就用到callable了。 

  FutureTask futureTask=new FutureTask(new Callable() {        @Override        public String call() throws Exception {            Thread.sleep(3000);            System.out.println("calld方法执行了");            return "call方法返回值";        }    });    futureTask.run();    System.out.println("获取返回值: " + futureTask.get());    FutureTask futureTask1=new FutureTask(new Callable() {        @Override        public String call() throws Exception {            Thread.sleep(3000);            System.out.println("calld方法执行了1");            return "call方法返回值1";        }    });    futureTask1.run();    System.out.println("获取返回值1: " + futureTask1.get());

我们可以调用futureTask.get()方法去获取线程异步的执行结果,

这时候问题又来了
那如果2个线程一起执行,futureTask执行完了,futureTask1没执行完会不会有问题。是不是futureTask1就拿不到结果了?
当然不会,futureTask.get()方法会保证线程在执行完之前是阻塞的。
我们看下futureTask源码

2个一个有时间,一个没有时间,最终都是调用的awaitDone()这个方法,我们继续看awaitDone

 

 

线程没有执行完,也就是没有到达COMPLETING的状态,会执行LockSupport.park,让线程等待,那什么时候去唤醒呢?

我们继续看

 

 最后返回线程的执行结果:

那么再问callable和Runnable有什么联系呢?

相信大家通过对源码的分析都明白了,callable的call()方法是被Runnable的run()方法调用的。
如果有不对的地方欢迎大家指正

原文:https://blog.csdn.net/qq_844085127/article/details/108872756

转载地址:https://blog.csdn.net/Aplumage/article/details/118718722 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:多线程之CAS与synchronized的比较
下一篇:多线程之BlockingQueue中 take、offer、put、add的一些比较

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月13日 08时14分21秒