java中Runnable和Callable的区别

简介: java中Runnable和Callable的区别

文章目录



java中Runnable和Callable的区别


在java的多线程开发中Runnable一直以来都是多线程的核心,而Callable是java1.5添加进来的一个增强版本。


本文我们会详细探讨Runnable和Callable的区别。


运行机制


首先看下Runnable和Callable的接口定义:


@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();
}


@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;
}


Runnable需要实现run()方法,Callable需要实现call()方法。


我们都知道要自定义一个Thread有两种方法,一是继承Thread,而是实现Runnable接口,这是因为Thread本身就是一个Runnable的实现:


class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    ...


所以Runnable可以通过Runnable和之前我们介绍的ExecutorService 来执行,而Callable则只能通过ExecutorService 来执行。


返回值的不同


根据上面两个接口的定义,Runnable是不返还值的,而Callable可以返回值。

如果我们都通过ExecutorService来提交,看看有什么不同:


  • 使用runnable


public void executeTask() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(()->log.info("in runnable!!!!"));
        executorService.shutdown();
    }


  • 使用callable


public void executeTask() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(()->{
            log.info("in callable!!!!");
            return "callable";
        });
        executorService.shutdown();
    }


虽然我们都返回了Future,但是runnable的情况下Future将不包含任何值。


Exception处理


Runnable的run()方法定义没有抛出任何异常,所以任何的Checked Exception都需要在run()实现方法中自行处理。


Callable的Call()方法抛出了throws Exception,所以可以在call()方法的外部,捕捉到Checked Exception。我们看下Callable中异常的处理。


public void executeTaskWithException(){
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future future = executorService.submit(()->{
            log.info("in callable!!!!");
            throw new CustomerException("a customer Exception");
        });
        try {
            Object object= future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
            e.getCause();
        }
        executorService.shutdown();
    }


上面的例子中,我们在Callable中抛出了一个自定义的CustomerException。


这个异常会被包含在返回的Future中。当我们调用future.get()方法时,就会抛出ExecutionException,通过e.getCause(),就可以获取到包含在里面的具体异常信息。


本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/runnable-callable

相关文章
|
9天前
|
Java
Java基础之 JDK8 HashMap 源码分析(中间写出与JDK7的区别)
这篇文章详细分析了Java中HashMap的源码,包括JDK8与JDK7的区别、构造函数、put和get方法的实现,以及位运算法的应用,并讨论了JDK8中的优化,如链表转红黑树的阈值和扩容机制。
13 1
|
13天前
|
Java 编译器 C语言
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
32 2
|
13天前
|
存储 缓存 Java
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
27 1
|
18天前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
44 1
|
18天前
|
缓存 安全 Java
Java中 final、finally、finalize 有什么区别?
本文详细阐述了Java中`final`、`finally`和`finalize`的区别:`final`用于修饰类、方法和变量以表示不可变性;`finally`是用于确保在`try-catch`结构中无论是否发生异常都能执行的代码块;而`finalize`是`Object`类的方法,用于在对象被垃圾回收前执行清理工作,但在JDK 9中已被标记为弃用。
14 0
Java中 final、finally、finalize 有什么区别?
|
18天前
|
Java
Java中抽象类和接口有什么区别?
本文阐述了Java中抽象类和接口的区别,包括类型扩展、方法/属性访问控制符、方法实现、使用目的等方面的不同,并提供了抽象类和接口的使用示例,以及Java中其他类型的类(普通类、内部类等)的简介。
17 0
Java中抽象类和接口有什么区别?
|
2天前
|
缓存 算法 Java
Java 中线程和纤程Fiber的区别是什么?
【10月更文挑战第14天】
10 0
|
5月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
74 1
|
2月前
|
并行计算 Java 大数据
Callable和Future
Callable和Future
|
5月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。