为什么需要 Callable?Runnable 的缺陷

先来看一下,为什么需要 Callable?要想回答这个问题,我们先来看看现有的 Runnable 有哪些缺陷?

不能返回一个返回值

第一个缺陷,对于 Runnable 而言,它不能返回一个返回值,虽然可以利用其他的一些办法,比如在 Runnable 方法中写入日志文件或者修改某个共享的对象的办法,来达到保存线程执行结果的目的,但这种解决问题的行为千曲百折,属于曲线救国,效率着实不高。

实际上,在很多情况下执行一个子线程时,我们都希望能得到执行的任务的结果,也就是说,我们是需要得到返回值的,比如请求网络、查询数据库等。可是 Runnable 不能返回一个返回值,这是它第一个非常严重的缺陷。

不能抛出 checked Exception

第二个缺陷就是不能抛出 checked Exception,如下面这段代码所示:

复制代码
public class RunThrowException {
 
   /**
    * 普通方法内可以 throw 异常,并在方法签名上声明 throws
    */
   public void normalMethod() throws Exception {
       throw new IOException();
   }
 
   Runnable runnable = new Runnable() {
       /**
        *  run方法上无法声明 throws 异常,且run方法内无法 throw 出 checked Exception,除非使用try catch进行处理
        */
       @Override
       public void run() {
           try {
               throw new IOException();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
}

在这段代码中,有两个方法,第一个方法是一个普通的方法,叫作 normalMethod,可以看到,在它的方法签名中有 throws Exception,并且在它的方法内也 throw 了一个 new IOException()。

然后在下面的的代码中,我们新建了一个 Runnable 对象,同时重写了它的 run 方法,我们没有办法在这个 run 方法的方法签名上声明 throws 一个异常出来。同时,在这个 run 方法里面也没办法 throw 一个 checked Exception,除非如代码所示,用 try catch 包裹起来,但是如果不用 try catch 是做不到的。

这就是对于 Runnable 而言的两个重大缺陷。

为什么有这样的缺陷
为什么有这样的缺陷呢?我们来看一下 Runnable 接口的定义:

复制代码
public interface Runnable {
   public abstract void run();
}
代码比较短小,Runnable 是一个 interface,并且里面只有一个方法,叫作 public abstract void run()。这个方法已经规定了 run() 方法的返回类型是 void,而且这个方法没有声明抛出任何异常。所以,当实现并重写这个方法时,我们既不能改返回值类型,也不能更改对于异常抛出的描述,因为在实现方法的时候,语法规定是不允许对这些内容进行修改的。

回顾课程之前小节的众多代码,从来没有出现过可以在 run 方法中返回一个返回值这样的情况。

Runnable 为什么设计成这样

我们再深入思考一层,为什么 Java 要把它设计成这个样子呢?

假设 run() 方法可以返回返回值,或者可以抛出异常,也无济于事,因为我们并没有办法在外层捕获并处理,这是因为调用 run() 方法的类(比如 Thread 类和线程池)是 Java 直接提供的,而不是我们编写的。

所以就算它能有一个返回值,我们也很难把这个返回值利用到,如果真的想弥补 Runnable 的这两个缺陷,可以用下面的补救措施——使用 Callable。

Callable 接口
Callable 是一个类似于 Runnable 的接口,实现 Callable 接口的类和实现 Runnable 接口的类都是可以被其他线程执行的任务。 我们看一下 Callable 的源码:

复制代码
public interface Callable<V> {
     V call() throws Exception;
}

可以看出它也是一个 interface,并且它的 call 方法中已经声明了 throws Exception,前面还有一个 V 泛型的返回值,这就和之前的 Runnable 有很大的区别。实现 Callable 接口,就要实现 call 方法,这个方法的返回值是泛型 V,如果把 call 中计算得到的结果放到这个对象中,就可以利用 call 方法的返回值来获得子线程的执行结果了。

Callable 和 Runnable 的不同之处

最后总结一下 Callable 和 Runnable 的不同之处:

  1. 方法名,Callable 规定的执行方法是 call(),而 Runnable 规定的执行方法是 run();
  2. 返回值,Callable 的任务执行后有返回值,而 Runnable 的任务执行后是没有返回值的;
  3. 抛出异常,call() 方法可抛出异常,而 run() 方法是不能抛出受检查异常的;

和 Callable 配合的有一个 Future 类,通过 Future 可以了解任务执行情况,或者取消任务的执行,还可获取任务执行的结果,这些功能都是 Runnable 做不到的,Callable 的功能要比 Runnable 强大。
引用:https://kaiwu.lagou.com/course/courseInfo.htm?courseId=16#/detail/pc?id=286

Java多线程学习三十二:Callable 和 Runnable 的不同?相关推荐

  1. Java多线程学习三十八:你知道什么是 CAS 吗

    CAS 简介 CAS 其实是我们面试中的常客,因为它是原子类的底层原理,同时也是乐观锁的原理,所以当你去面试的时候,经常会遇到这样的问题"你知道哪些类型的锁"?你可能会回答&quo ...

  2. Java多线程学习三十四:使用 Future 有哪些注意点?Future 产生新的线程了吗

    Future 的注意点 1. 当 for 循环批量获取 Future 的结果时容易 block,get 方法调用时应使用 timeout 限制 对于 Future 而言,第一个注意点就是,当 for ...

  3. Java多线程学习三十六:主内存和工作内存的关系

    CPU 有多级缓存,导致读的数据过期 由于 CPU 的处理速度很快,相比之下,内存的速度就显得很慢,所以为了提高 CPU 的整体运行效率,减少空闲时间,在 CPU 和内存之间会有 cache 层,也就 ...

  4. Java多线程学习三十:ThreadLocal 适合用在哪些实际生产的场景中

    我们在学习一个工具之前,首先应该知道这个工具的作用,能带来哪些好处,而不是一上来就闷头进入工具的 API.用法等,否则就算我们把某个工具的用法学会了,也不知道应该在什么场景下使用.所以,我们先来看看究 ...

  5. Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题

    线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...

  6. Java多线程学习三十九:CAS 有什么缺点?

    CAS 有哪几个主要的缺点. 首先,CAS 最大的缺点就是 ABA 问题. 决定 CAS 是否进行 swap 的判断标准是"当前的值和预期的值是否一致",如果一致,就认为在此期间这 ...

  7. Java多线程学习三十五: CyclicBarrier 和 CountDownLatch 有什么不同

    CyclicBarrier 和 CountDownLatch 有什么不同? CyclicBarrier作用 CyclicBarrier 和 CountDownLatch 确实有一定的相似性,它们都能阻 ...

  8. Java开发学习(三十四)----Maven私服(二)本地仓库访问私服配置与私服资源上传下载

    一.本地仓库访问私服配置 我们通过IDEA将开发的模块上传到私服,中间是要经过本地Maven的 本地Maven需要知道私服的访问地址以及私服访问的用户名和密码 私服中的仓库很多,Maven最终要把资源 ...

  9. Java架构学习(十二)java内存结构新生代老年代JVM参数调优堆内存参数配置解决堆栈溢出

    JVM参数调优与垃圾回收机制 一.java内存结构 Java内存模型:是多线程里面的,jmm与线程可见性有关 Java内存结构:是JVM虚拟机存储空间. Java内存结构图 Java内存机构分为:方法 ...

最新文章

  1. Crystal Reports中的字段
  2. 图灵奖得主Yann LeCun万字访谈:DNN“史前文明”、炼金术及新的寒冬
  3. 两个什么漏洞,可让十亿安卓手机被获取Root权限?
  4. 【Opencv实战】趣味应用 | 用OpenCV自动给图片添加虚拟特效---平淡的生活需要技术的点缀~
  5. Spring Cloud 爆高危漏洞!!!
  6. 问题小结(二)——maven的核心功能、面向对象编程和面向接口编程的区别、抽象类和接口的区别等
  7. resin php mysql_RedhatAS4.0上安装Apache2+PHP5+MySQL+Resin+SSL+GD+webalizer
  8. 为了偷吃东西你能有多拼?! | 今日最佳
  9. linux redis 普通用户,非root用户安装redis
  10. 利用jquery load 局部刷新数据
  11. raiden_graph
  12. [Windows Server 2008] 404错误设置方法
  13. CodeCanyon上的12种最佳CSS动画
  14. 格力不需要“第二个董明珠”
  15. AMBA协议之AXI协议——中文翻译
  16. 【游戏客户端开发】Unity3D 学习笔记2——了解U3D引擎的操作面板和各种工具
  17. ssm:Unable to process Jar entry
  18. F1-F12键的作用
  19. uniapp开发聊天APP踩坑记录
  20. Epalloy8240亨斯迈Huntsman低粘度、低水解氯、反应活性高官能度为2.35的酚醛环氧树脂

热门文章

  1. BAT与华为职级薪资股权大揭秘 网友看完后很酸表示“雨女无瓜”
  2. 5G加持!刘作虎确认一加7 Pro:屏幕成本是普通旗舰2倍
  3. 三星开出的57619美元年薪 却还是留不住千禧一代
  4. 继苏宁京东后 拼多多也宣布下调新款iPhone售价
  5. 5G手机还没普及 LG电子就已着手研发6G
  6. python形式参数和实际参数_python学习笔记3:函数和参数
  7. 项目背景怎么描述_培训回顾 |第六届“互联网+”之创业大赛项目计划书撰写
  8. AudioTrack 播放PCM音频数据
  9. 译林 五年级上 单词_牛津译林版九年级英语上Unit1单元重点单词、词组和句型总结...
  10. dhcp地址分配信息是什么_网络资讯:DHCP 是什么意思