Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >并发编程系列之Callable和Runnable的不同?

并发编程系列之Callable和Runnable的不同?

作者头像
SmileNicky
发布于 2021-09-08 07:04:41
发布于 2021-09-08 07:04:41
41310
代码可运行
举报
文章被收录于专栏:Nicky's blogNicky's blog
运行总次数:0
代码可运行

本博客学习要点:

  • 1、了解Runnable的原理和不足
  • 2、掌握怎么使用Callable实现任务
  • 3、对比Runnable和Callable的不同

ps:基于Jdk1.8看源码

1、Runnable入门实例

并发编程系列之Callable和Runnable的不同?在学习并发多线程的过程中,很多读者都知道怎么实现Runnable,下面是一道经典的例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public  static void main(String[] args) {
	Thread t  = new Thread(new RunnableTask ());
	t.start();
}
static class RunnableTask implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

2、Runnable有什么缺陷?

对于Callable,可能有些读者就不是很熟悉了,在上一章节多线程基础知识的学习中,我们知道了Runnable和Callable其实可以用来表示多线程的任务,而在多线程的方法中,我们是没有找到可以传入Callable对象的具体方法的

然后Callable要怎么使用?为什么要设计出Callable?Runnable是不是有什么缺陷?ok,还是先看看Runnable的源码:可以看出Runable其实就是一个接口,同时使用了java的函数式函数@FunctionalInterface,所以是可以支持lambda表达式的,这是jdk8中的新特性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

然后Runnable有什么缺陷?

  • (1)、没有返回值 Runnablerun方法是void类型的,没有返回值,虽然可以在实现的run方法里写入日志文件或者修改某个共享的对象的办法,来达到保存线程执行结果的目的,不过这样实现确实比较麻烦。 实际上,在很多情况下执行一个子线程时,我们都希望能得到执行的任务的结果,可是 Runnable 不能返回一个返回值,这是它第一个非常严重的缺陷。
  • (2)不能抛出 checked Exception Runnable是不能抛出 checked Exception的,run方法是不允许在声明throws Exception的, 且run方法内无法 throw 出 checked Exception,除非使用try catch进行处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Runnable runnable = new Runnable() {
    /**
     * run方法是不允许在声明throws Exception的,
     * 且run方法内无法 throw 出 checked Exception,
     * 除非使用try catch进行处理
     */
    @Override
    public void run() {
        try {
            throw new IOException();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
};
}

3、Runnable 为什么设计成这样?

知道了Runnable的缺陷后,我们可能会好奇为什么之前这样设计?假设run方法可以抛出checked Exception,也可以有返回值,也无济于事,因为run方法调用,我们是通过Thread类或者是线程池IUC的api去调用的,所以我们是不可以在外层就捕获到Exception的。

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

4、Callable需要怎么调用?

调用Callable任务有两种使用方法,一种是使用线程池,另外一种是使用FutureTask调用

使用线程池的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void callableExecutorService() throws InterruptedException, ExecutionException {
     ExecutorService service = new ThreadPoolExecutor(10, 10,
             60L, TimeUnit.SECONDS,
             new ArrayBlockingQueue(10));

     Future<Integer> future = service.submit(new CallableTask());
     Thread.sleep(3000);
     System.out.println("future is done?" + future.isDone());
     if (future.isDone()) {
         System.out.println("callableTask返回参数:"+future.get());
     }
     service.shutdown();
}

static class CallableTask implements Callable<Integer> {
    @Override
    public Integer call() {
        return ThreadLocalRandom.current().ints(0, (99 + 1)).limit(1).findFirst().getAsInt();
    }
}

使用FutureTask的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void callableFutureTask() throws InterruptedException, ExecutionException {
    CallableTask task = new CallableTask();
    FutureTask futureTask = new FutureTask(task);
    Thread t = new Thread(futureTask);
    t.start();
    Thread.sleep(1000L);
    System.out.println("task result:" + futureTask.get());
}
static class CallableTask implements Callable<Integer> {
    @Override
    public Integer call() {
        return ThreadLocalRandom.current().ints(0, (99 + 1)).limit(1).findFirst().getAsInt();
    }
}

5、Callable 和 Runnable 的不同之处

对于Runnable前面已经介绍过,使用现在翻下Callable的源码:可以看出Callable本质也是一个接口,也和Runnable一样也支持函数式接口,不过不同的是Callable使用了V这个泛型,所以是可以支持返回值的,而且也有throws Exception,所以可以获取到checked Exception

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

ok,可以归纳一下Callable和Runnable的不同:

1、方法名,Runnable的方法名是run,而Callable的方法名是call 2、抛出异常,Runnable不支持抛出异常,而Callable支持抛出checked Exception 3、返回值,Runnable不支持返回值,而Callable是支持返回值的 4、是否支持Future使用,Runnable不支持,Callable是可以组合线程池或者FutureTask一起使用,同时可以将结果返回给Future,通过 Future 可以了解任务执行情况,或者取消任务的执行

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/09/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
FutureTask可以使用Runable
FutureTask可以使用Runable
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Java-多线程:Callable接口和Runnable接口之间的区别
想学习好Future设计模式,我们应当首先将Callable、以及Runnable接口之间的区别弄明白: 不妨首先给出他们俩的源代码:
Fisherman渔夫
2020/02/18
7.6K0
(八)Callable和Runnable的区别
Runnable只有一个run方法,在使用普通线程的时候,我们可以实现Runnable接口即可,Thread类在调用start()函数后就是执行的是Runnable的run()函数。
HaC
2020/12/30
4590
并非编程系列之创建线程的方法有多少种?
并非编程系列之创建线程的方法有多少种?并发多线程的知识是很重要而且比较杂的知识点,所以需要花不少时间用于整理。创建线程的方式是学习并发编程的一个很基础的问题,所以必须先掌握好
SmileNicky
2021/08/24
4570
一次性解决老大难问题:线程治理 Futrue、Callable接口、CompletableFuture
线程治理最重要的是线程池了,之前我讲过,但是,还有两大法宝就是future 和 callable
Joseph_青椒
2023/08/26
1K0
一次性解决老大难问题:线程治理 Futrue、Callable接口、CompletableFuture
java中Runnable和Callable的区别
在java的多线程开发中Runnable一直以来都是多线程的核心,而Callable是java1.5添加进来的一个增强版本。
程序那些事
2020/07/08
8220
采用线程池进行异步任务处理
被@Async修饰的方法叫做异步方法,这些异步方法会在新的线程中进行处理,不影响主线程的顺序执行。
春哥大魔王
2018/07/23
3.3K0
多线程(四) | 聊聊Callable和Future
通过前面几篇文章,我相信大家应该对于如何使用多线程执行任务应该都有了一定的了解。今天我们来讲一讲Callable和Future。
一缕82年的清风
2022/11/02
5570
Runnable 和Callable的实现与区别,应用场景
1:通过实现Runnable接口 2:通过继承Thread接口 3:通过Callable和Future创建线程
全栈程序员站长
2022/07/25
1.5K0
Future和Callable学习
我们知道使用多线程时,最初的Thread到线程池,此时对于线程的使用,提供了其使用的复用率。而实现多线程的三种方式:继承Thread;实现Runnable接口,重写run方法;实现Callable接口,同时重写call方法,同时通过Future获取执行的返回值。也就是说callable执行任务,而Future拿到执行的结果。Future具有阻塞性在于其get()方法具有阻塞性,而isDone()是不具有阻塞性的。
路行的亚洲
2020/07/16
5030
并发编程系列之FutureTask源码学习笔记
在上一章节的学习中,我们知道了Future类的基本用法,知道了Future其实就是为了监控线程任务执行的,接着本博客继续学习FutureTask。然后什么是FutureTask类?
SmileNicky
2021/09/08
3040
Java中的Runnable、Callable、Future、FutureTask的区别
Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。
开发者技术前线
2020/11/23
4620
JUC系列(六) | Callable和Future接口详解&使用、FutureTask应用 获取异步线程返回值
在上上篇文章中,创建线程那个小角落,提到了这个,但是当时只是匆匆忙忙讲了一下。到这里再全面性的讲解一下。
宁在春
2022/10/31
1.1K0
JUC系列(六) | Callable和Future接口详解&使用、FutureTask应用 获取异步线程返回值
【原创】Java并发编程系列36 | FutureTask
线程池源码中出现了很多Callable、Future、FutureTask等以前没介绍过的接口,尤其是线程池提交任务时总是把任务封装成FutureTask,今天就来为大家解惑:
java进阶架构师
2020/09/22
3600
【原创】Java并发编程系列36 | FutureTask
【小家Java】Future、FutureTask、CompletionService、CompletableFuture解决多线程并发中归集问题的效率对比
开启线程执行任务,不管是使用Runnable(无返回值不支持上报异常)还是Callable(有返回值支持上报异常)接口,都可以轻松实现。那么如果是开启线程池并需要获取结果归集的情况下,如何实现,以及优劣?
YourBatman
2019/09/03
2.7K1
【小家Java】Future、FutureTask、CompletionService、CompletableFuture解决多线程并发中归集问题的效率对比
6.实现 Callable 接口
6.实现 Callable 接口 前言 本篇章来介绍一下创建线程的第三种方式,其中创建线程一共有四种方式: 继承 Thread 类 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式 那么下面我们来介绍一下 实现 Callable 接口的方式。 Callable 接口 - Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式:Callable 接口 - Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程
Devops海洋的渔夫
2022/03/23
5980
6.实现 Callable 接口
死磕Juc(一)之CompletableFuture
Future接口定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任
yuanshuai
2022/08/17
5600
死磕Juc(一)之CompletableFuture
老徐和阿珍的故事:Runnable和Callable有什么不同?
阿珍探出头看了看老徐的屏幕,全部都是绿色的曲线图,好奇地问:“老徐,你看的这是什么?”老徐看的太入神,转过头才发现阿珍,尬尴地笑了笑说:“我就是看看最近的行情。”老徐立马切换了窗口。
万猫学社
2022/06/14
6260
老徐和阿珍的故事:Runnable和Callable有什么不同?
Callable and Future in Java(java中的Callable和Future)
通常,我们有两种方式创建线程,一种方式是继承Thread类,另外一种方式是实现Runnable接口。然而,Runnable方式缺少的一个特性就是,当线程终止的时候,即run运行完成的时候,我们布恩那个让线程返回一个执行结果。为了之处这个特性,在java中就增加了Callable接口。
冬天里的懒猫
2020/09/28
4920
简单理解Callable接口
Callable,新启线程的一种方式,返回结果并且可能抛出异常的任务,在前面的新启线程的文章中用过,但是没有具体讲解
彼岸舞
2020/11/06
8630
并发多线程学习(三)Java多线程入门类和接口
上一章我们了解了操作系统中多线程的基本概念。那么在Java中,我们是如何使用多线程的呢?
用户10168815
2023/02/28
3530
推荐阅读
相关推荐
Java-多线程:Callable接口和Runnable接口之间的区别
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验