目录
  1. 1. Runnable和Callable接口解析
    1. 1.1. Runnable解析
    2. 1.2. Callable解析
    3. 1.3. Callable和Runnable的区别:
02-Runnable和Callable接口解析

Runnable和Callable接口解析

Runnable解析

  Runnable是一个接口,它只有一个run()抽象方法,run()抽象方法需要被实现后才能使用.

1
2
3
public interface Runnable {
public abstract void run();
}

run()方法的返回值是void,故在执行完任务后无法返回任何结果
  Thread类继承了Runnable接口,并且Thread中实现了run()方法.最后通过Thread类的start()方法就可以启动线程了.这是我们平时在应用中使用线程的常用方法
思考以下问题:

  • 为什么调用start()方法就可以启动线程,而不是调用run().start()方法和决定线程运行内容的run()方法又有什么联系呢?
  • 在Runnable层面实现run()方法和Thread层面实现run()方法的区别
  • 怎么用Runnable实现run方法,并在Thread中执行Runnable实例化后重写的run方法

  打开如下Runnable的源码,我们可以发现,它只含有一个抽象的run()方法.因为它是接口,所以需要被继承后重写run()方法才能使用

思考:
  如果需要启动一个新的线程,这意味着需要分配给它CPU资源来执行这个线程,而CPU是不归JVM(Java虚拟机)直接管辖的,自然需要通过JVM通过外部的接口来实现和操作系统的对话,调整CPU资源的分配,所以,线程的创建一定是一个native方法(实现Java调用底层的C、C++代码).接口中的run()方法中的内容,仅仅代表线程运行的内容.一个结论出来了,Thread类中必然有native方法,Runnable无法脱离Thread类来新建线程.如果我们在new一个线程对象后直接调用run方法,也只是让当前线程去执行run()方法中的语句罢了,并没有实现多线程
  在多线程的应用中我们更加倾向于使用Runnable来实现run()方法,因为这可以使得多线程在执行相同的代码的同时操作相同成员变量(多线程共享资源).因此,多线程的最佳打开方式是:写一个类继承Runnable接口,重写run()方法,再以Thread为媒介启动线程

Callable解析

  Callable是java.util.concurrent包下的,也是一个接口,也只有一个call()方法,类似于java.lang.Runnable的run()方法,实现Callable接口的类和实现Runnable接口的类都是可以被其它线程执行的任务
可以看到call()方法是有返回值的,可以将执行的结果返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 一个任务返回的结果可能抛出异常,继承者定义了一个单例的没有参数的方法被称为call
* Callable接口与Runnable接口相似,这两个都是为那些可能被其他线程的执行的实例的类设计的
* Runnable不会返回一个结果,也不会跑出checked异常
* Executor类包括多种方法来将其他普通形式转化为Callable类
*/
@FunctionalInterface
public interface Callable<V> {
/**
* 计算一个结果或者抛出一个不能执行的异常
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}

Callable和Runnable的区别:

  1. Callable中定义的是call()方法,Runnable中定义的是run()方法
  2. Callable中的call()方法可以返回执行任务后的结果,Runnable中的run()方法无法获得返回值
  3. Callable中的call()方法定义了throws Exception抛出异常,抛出的异常可以在主线程Future.get()时被主线程捕获;Runnable中的run()方法没有定义抛出异常,运行任务时发生异常时也会上抛,因为即使不加默认也会上抛RuntimeException,但异常无法被主线程获取
  4. 运行Callable任务可以拿到一个Future对象代表异步运算的结果
文章作者: Eric Liang
文章链接: https://ericql.github.io/2019/11/12/02-Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/02-%E5%B9%B6%E5%8F%91%E5%8C%85/02-Runnable%E5%92%8CCallable%E6%8E%A5%E5%8F%A3%E8%A7%A3%E6%9E%90/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Eric Liang
打赏
  • 微信
  • 支付宝