runnable 和 callable 有什么区别

简介: Runnable和Callable都是用于实现多线程的接口,区别在于返回结果、异常处理、阻塞和结果处理等方面。选择使用Runnable还是Callable取决于任务的需求和场景。

Runnable和Callable都是在Java中用于实现多线程的接口,它们的目的都是为了执行一段任务并返回结果。它们之间有以下几个主要区别:

返回结果:Runnable接口的run()方法没有返回值,它只是执行一段任务,而Callable接口的call()方法可以返回一个结果,这个结果可以是任意类型。

异常处理:Runnable接口的run()方法不能抛出异常,而Callable接口的call()方法可以抛出异常。当使用Callable时,如果任务抛出了异常,可以通过捕获Callable中的异常来处理。

是否进行阻塞:在使用Runnable时,我们通常使用Thread类来启动一个线程,并通过调用Thread的start()方法来执行Runnable的run()方法。而在使用Callable时,我们必须使用ExecutorService的submit()方法来提交Callable任务,并且它会返回一个Future对象,我们可以通过Future对象来获取执行结果。在获取Callable执行结果时,如果任务还未完成,一般会阻塞等待任务完成并获取结果。

执行结果的处理:Callable的call()方法可以返回一个Future对象,通过这个Future对象可以判断任务是否完成、取消任务执行以及获取任务执行结果。而Runnable没有这样的机制,无法直接获取任务的执行结果。

综上所述,Runnable适合那些不需要返回结果的任务,而Callable适合那些需要返回结果并可能抛出异常的任务。通常情况下,如果不需要获取任务的执行结果,可以使用Runnable接口;如果需要获取任务的执行结果,可以使用Callable接口,并结合ExecutorService的submit()方法来提交任务并获取执行结果。

下面是一个简单的示例代码,展示了如何使用Runnable和Callable:

java

import java.util.concurrent.*;

public class ThreadExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);

    // 使用Runnable
    Runnable runnableTask = () -> {
        System.out.println("Runnable task is executing.");
    };
    executor.execute(runnableTask);

    // 使用Callable
    Callable<String> callableTask = () -> {
        System.out.println("Callable task is executing.");
        return "Callable Result";
    };
    Future<String> future = executor.submit(callableTask);

    try {
        String result = future.get();
        System.out.println("Callable task result: " + result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }

    executor.shutdown();
}

}

在这个示例中,我们创建了一个线程池,并通过ExecutorService的execute()方法执行了一个Runnable任务,以及通过submit()方法执行了一个Callable任务。在获取Callable任务的执行结果时,我们使用Future对象进行等待和获取。

总之,Runnable和Callable都是用于实现多线程的接口,区别在于返回结果、异常处理、阻塞和结果处理等方面。选择使用Runnable还是Callable取决于任务的需求和场景。

相关文章
|
3月前
|
Java
Java中Runnable和Callable有什么不同
【8月更文挑战第9天】Java中Runnable和Callable有什么不同
18 1
|
4月前
|
存储 缓存 安全
(八)深入并发之Runnable、Callable、FutureTask及CompletableFuture原理分析
关于Runnable、Callable接口大家可能在最开始学习Java多线程编程时,都曾学习过一个概念:在Java中创建多线程的方式有三种:继承Thread类、实现Runnable接口以及实现Callable接口。但是实则不然,真正创建多线程的方式只有一种:继承Thread类,因为只有`new Thread().start()`这种方式才能真正的映射一条OS的内核线程执行,而关于实现Runnable接口以及实现Callable接口创建出的Runnable、Callable对象在我看来只能姑且被称为“多线程任务”,因为无论是Runnable对象还是Callable对象,最终执行都要交由Threa
|
6月前
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
44 0
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
|
6月前
|
安全 Java
多线程(CAS, ABA问题, Runnable & Callable & 僵尸线程 & 孤儿进程)
多线程(CAS, ABA问题, Runnable & Callable & 僵尸线程 & 孤儿进程)
60 1
|
6月前
|
Java
创建线程的三种方式:继承Thread、Runnable 接口、Callable 接口
创建线程的三种方式:继承Thread、Runnable 接口、Callable 接口
runnable 和 callable 有什么区别
runnable 和 callable 有什么区别
|
缓存 Java 数据库连接
线程的创建、Lambda函数式接口?Runnable和Callable之间的适配?动态修改线程任务?这里带你图解Java线程池
上面只是提到了对于Thread执行任务的一种动态实现方法,肯定还有其他的。 那么动态实现有什么好处呢? 当我们有很多个任务的时候,我们如果一直使用new,再让gc的话,那么对于系统资源的消耗无疑是巨大的。 那么这个时候,如果我们固定一下,专门拿几个线程来处理并发任务呢?但是当并发任务很多又该怎么办? 这个时候就引入了池化思想 —— Pool 什么是池? 在学JDBC的时候我们知道了连接池,在学Spring的时候,我们又接触到了对象池。 其实按理来说线程池应该是大家在初学JavaSE的时候应该就遇到的,这里我们再来讲一下。 线程池,就是用一个容器来管理线程,这个容器叫做池(Poo
113 0
线程的创建、Lambda函数式接口?Runnable和Callable之间的适配?动态修改线程任务?这里带你图解Java线程池
|
6月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
80 1
|
3月前
|
并行计算 Java 大数据
Callable和Future
Callable和Future
|
6月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。