Java并发编程78讲--48 第48讲:Callable 和 Runnable 的不同?

你好,欢迎来到第 48 课时,在本课时我们将讲解 Callable 和 Runnable 的不同。

为什么需要 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 的不同之处:

  • 方法名,Callable 规定的执行方法是 call(),而 Runnable 规定的执行方法是 run();
  • 返回值,Callable 的任务执行后有返回值,而 Runnable 的任务执行后是没有返回值的;
  • 抛出异常,call() 方法可抛出异常,而 run() 方法是不能抛出受检查异常的;
  • 和 Callable 配合的有一个 Future 类,通过 Future 可以了解任务执行情况,或者取消任务的执行,还可获取任务执行的结果,这些功能都是 Runnable 做不到的,Callable 的功能要比 Runnable 强大。

以上就是本课时的内容了。首先介绍了 Runnable 的两个缺陷,第一个是没有返回值,第二个是不能抛出受检查异常;然后分析了为什么会有这样的缺陷,以及为什么设计成这样;接下来分析了 Callable 接口,并且把 Callable 接口和 Runnable 接口的区别进行了对比和总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[JAVA工程师必会知识点之并发编程]1、现在几乎100%的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。2、现在已经是移动互联和大数据时代,对于应用程序的性能、处理能力、处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。3、并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行、接口响应、批处理效率更高,必须使用并发编程。4、并发编程是中高级程序员的标配,是拿高薪的必备条件。 【主师】尹洪亮Kevin:现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。10余年软件行业经验,具有数百个线上项目实战经验。擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行【推荐你学习这门课的理由:知识体系完整+丰富学习资料】1、 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础、进阶、精通篇、Disruptor高并发框架、RateLimiter高并发访问限流吗,BAT员工也在学。2、课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。3、本课程0基础入门,从进程、线程、JVM开始起,每一个章节只专注于一个知识点,每个章节均有代码实例。 【课程分为基础篇、进阶篇、高级篇】一、基础篇基础篇从进程与线程、内存、CPU时间片轮训起,包含线程的3种创建方法、可视化观察线程、join、sleep、yield、interrupt,Synchronized、重入锁、对象锁、类锁、wait、notify、线程上下文切换、守护线程、阻塞式安全队列等内容。二、进阶篇进阶篇课程涵盖volatied关键字、Actomic类、可见性、原子性、ThreadLocal、Unsafe底层、同步类容器、并发类容器、5种并发队列、COW容器、InheritableThreadLocal源码解析等内容。三、精通篇精通篇课程涵盖JUC下的核心工具类,CountDownLath、CyclicBarrier、Phaser、Semaphore、Exchanger、ReentrantLock、ReentrantReadWriteLock、StampedLock、LockSupport、AQS底层、悲观锁、乐观锁、自旋锁、公平锁、非公平锁、排它锁、共享锁、重入锁、线程池、CachedThreadPool、FixedThreadPool、ScheduledThreadPool、SingleThreadExecutor、自定义线程池、ThreadFactory、线程池切面编程、线程池动态管理等内容,高并发设计模式,Future模式、Master Worker模式、CompletionService、ForkJoin等课程中还包含Disruptor高并发无锁框架解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。高并发访问限流解:涵盖木桶算法、令牌桶算法、Google RateLimiter限流开发、Apache JMeter压力测试实战。 【学完后我将达到什么水平?】1、 吊打一切并发编程相关的笔试题、面试题。2、 重构自己并发编程的体系知识,不再谈并发色变。3、 精准掌握JAVA各种并发工具类、方法、关键字的原理和使用。4、 轻松上手写出更高效、更优雅的并发程序,在工作中能够提出更多的解决方案。  【面向人群】1、 总感觉并发编程很难、很复杂、不敢学习的人群。2、 准备跳槽、找工作、拿高薪的程序员。3、 希望提高自己的编程能力,开发出更高效、性能更强劲系统的人群。4、 想要快速、系统化、精准掌握并发编程的人群。【课程知识体系图】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值