人物背景

老徐,男,本名徐福贵,从事Java相关研发工作多年,职场老油条,摸鱼小能手,虽然岁数不大但长的比较着急,人称老徐。据说之前炒某币败光了所有家产,甚至现在还有欠债。

阿珍,女,本名陈家珍,刚刚入职不久的实习生,虽然是职场菜鸟但聪明好学。据说是学校的四大校花之一,追求她的人从旺角排到了铜锣湾,不过至今还单身。

阿珍探出头看了看老徐的屏幕,全部都是绿色的曲线图,好奇地问:“老徐,你看的这是什么?”老徐看的太入神,转过头才发现阿珍,尬尴地笑了笑说:“我就是看看最近的行情。”老徐立马切换了窗口。

阿珍没在意又继续问到:“RunnableCallable两个接口我总搞混,这个到底有什么不同?”

面对阿珍的灵魂拷问,老徐淡定自若地说:“Runnable是用于提供多线程任务支持的核心接口,Callable是在Java 1.5中添加的Runnable的改进版本。”

“在聊它们不同之前,我们先分别了解一下两个接口。”老徐一边说着,一边打开了源码:

Runnable接口

@FunctionalInterface
public interface Runnable {
public abstract void run();
}

Runnable接口是一个函数式接口,它只有一个run()方法,不接受任何参数,也不返回任何值。由于方法签名没有指定throws子句,因此无法进一步传播已检查的异常。它适用于我们不使用线程执行结果的情况,例如,异步打印日志:

package one.more;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class LoggingTask implements Runnable { private static Logger logger = LoggerFactory.getLogger(LoggingTask.class); private String name; public LoggingTask(String name) {
this.name = name;
} @Override
public void run() {
logger.info("{}说:你好!", this.name);
}
}

在上面例中,根据name参数把信息记录在日志文件中,没有返回值。我们可以通过Thread启动,比如:

public static void main(String[] args) {
String name = "万猫学社";
Thread thread = new Thread(new LoggingTask(name));
thread.start();;
}

我们也可以通过ExecutorService启动,比如:

public static void main(String[] args) {
String name = "万猫学社";
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new LoggingTask(name));
executorService.shutdown();
}

Callable接口

@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}

Callable接口也是一个函数式接口,它只有一个call()方法,不接受任何参数,返回一个泛型值V,在方法签名上包含throws Exception子句,因此我们可以很容易地进一步传播已检查异常。它适用于我们使用线程执行结果的情况,例如,异步计算阶乘:

package one.more;

import java.util.concurrent.Callable;

public class FactorialTask implements Callable<Integer> {

    private int n;

    public FactorialTask(int n) {
this.n = n;
} @Override
public Integer call() throws IllegalArgumentException {
int fact = 1;
if (n < 0) {
throw new IllegalArgumentException("必须大于等于零");
}
for (int i = n; i > 1; i--) {
fact = fact * i;
}
return fact;
}
}

在上面例中,根据n参数计算它的阶乘,并可以返回计算结结果。我们只能通过ExecutorService启动,比如:

public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(new FactorialTask(5));
System.out.println(future.get());
executorService.shutdown();
}

call()方法的结果可以通过Future对象获取到,如果在调用Future对象的get()方法时,call()方法出现了异常,异常会被继续传递,比如:

public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(new FactorialTask(-1));
System.out.println(future.get());
executorService.shutdown();
}

抛出如下异常:

老徐回头看看了阿珍,说:“这回你知道有什么不同了吧!”阿珍一头雾水地说:“信息量有点大呀,可以给我总结一下吗?”“当然可以。”老徐回答。

总结

Runnable和Callable的不同:

  • Callable的任务执行后可返回值,Runnable的任务不能返回值。
  • Callable只可以通过ExecutorService启动,Runnable可以通过ThreadExecutorService启动。
  • Callable的call()方法可以传播已检查异常,Runnable的run()方法不可以。

最后,谢谢你这么帅,还给我点赞关注

微信公众号:万猫学社

微信扫描二维码

关注后回复「电子书」

获取12本Java必读技术书籍

老徐和阿珍的故事:Runnable和Callable有什么不同?的更多相关文章

  1. 老徐和阿珍的故事:ArrayList和LinkedList的效率到底哪个高?

    人物背景: 老徐,男,本名徐福贵,从事Java相关研发工作多年,职场老油条,摸鱼小能手,虽然岁数不大但长的比较着急,人称老徐.据说之前炒某币败光了所有家产,甚至现在还有欠债. 阿珍,女,本名陈家珍,刚 ...

  2. 老徐和阿珍的故事:CAP是什么?超级爱放P吗?

    人物背景: 老徐,男,本名徐福贵,从事Java相关研发工作多年,职场老油条,摸鱼小能手,虽然岁数不大但长的比较着急,人称老徐.据说之前炒某币败光了所有家产,甚至现在还有欠债. 阿珍,女,本名陈家珍,刚 ...

  3. 老徐FrankXuLei 受邀为花旗银行讲授《微软WCF服务分布式开发与SOA架构设计课程》

    老徐FrankXuLei 受邀为花旗银行上海研发中心讲授<微软WCF服务分布式开发与SOA架构设计课程> 受邀为花旗银行上海研发中心讲授<微软WCF服务分布式开发与SOA架构设计课程 ...

  4. Runnable、Callable、Future和FutureTask用法

    http://www.cnblogs.com/dolphin0520/p/3949310.html java 1.5以前创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable ...

  5. Java多线程Runnable与Callable区别与拓展

    我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...

  6. Runnable和Callable之间的区别

    Runnable和Callable之间的区别 1.Runnable任务执行后没有返回值:Callable任务执行后可以获得返回值 2.Runnable的方法是run(),没有返回值:Callable的 ...

  7. Runnable和Callable 的区别

    Runnable和Callable 的区别 01.Runnable接口中只有一个run()没有返回值 没有声明异常   Callable接口中只有一个call()有返回值 有声明异常 02.Calla ...

  8. Runnable和Callable接口辨析

    突然发现和启动一个线程有关的有三函数,run(), call(), start(),有点小乱,所以特别梳理一下 首先说一下start(),这个是最好说的,感觉start()和run()这俩名字是真的有 ...

  9. java 并发包runnable 与 callable

    1.runnable 与 callable区别 2.避免callable执行完任务,获取返回结果时,阻塞其他子线程 下面固定线程池,设置4个,表明同时只有4个线程在执行任务,当某个线程执行完一个任务, ...

随机推荐

  1. Spring Security 介绍

    Spring Security介绍 开源 提供企业级的安全认证和授权 Spring安全拦截器 认证管理器 认证模式 Basic HTTP 1.0中使用的认证方法,使用用户名和密码Base64编码的方式 ...

  2. linux下gdb如何处理coredump错误

    linux下gdb如何处理coredump错误 在编写C++程序中,我们经常会遇到一种错误,segment fault, 这种coredump错误 会导致程序运行时异常退出或者终止,这种错误没有明显错 ...

  3. 我们一起来学Shell - shell的条件判断

    文章目录 Shell 条件测试语法 符号说明 Shell 测试表达式 文件测试表达式 字符串测试表达式 整数操作符 逻辑操作符 测试表达式的区别总结 Shell 条件判断之if语句 单分支 IF 条件 ...

  4. 面向对象—多态、鸭子类型(Day21)

    编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...

  5. VS Code开发TypeScript

    TypeScript是JaveScript的超集,为JavaScript增加了很多特性,它可以编译成纯JavaScript在浏览器上运行.TypeScript已经成为各种流行框架和前端应用开发的首选. ...

  6. Python-Flask框架之"图书管理系统"项目,附详解源代码及页面效果截图

    该图书管理系统要实现的功能如下: 1. 可以通过添加窗口添加书籍或作者,如果要添加的作者和书籍已存在于书架上, 则给出相应的提示: 2. 如果要添加的作者存在,而要添加的书籍书架上没有,则将该书籍添加 ...

  7. 攻防世界之Web_upload1

    题目: 本题考查的是文件上传漏洞. 上传一句话木马. 桌面新建一个webshell.php文本文件,写入<?php @eval($_POST['pass']);?>保存.  点击浏览,选择 ...

  8. HttpClient的使用(get、post请求)

    添加pom依赖 <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <d ...

  9. AfterLogicWebMail CSRF导致密码可修改

    实验目的 了解CSRF漏洞导致Webmail管理员帐号密码任意被修改 实验原理 当我们打开或者登陆某个网站的时候,浏览器与网站所存放的服务器将会产生一个会话(cookies),在这个会话没有结束时,你 ...

  10. Keepalived非抢占模式配置

    一.前言 HA的实际运行过程中,当主机发生异常,且后期恢复正常后,存在抢占或非抢占两种情况. 结合实际需求,可能有很多用户需要非抢占的HA工作模式.keepalived能够很好的支持这一需求. 二.k ...