Runnable和Callable

Java多线程实现:Runnable与Callable接口详解及对比
本文详细介绍了Java中创建多线程的两种主要方式:实现Runnable接口和继承Thread类。通过实例解析了Runnable接口的实现步骤,强调了Thread类内部如何调用Runnable的run()方法。同时,对Callable接口进行了讲解,说明了其call()方法能返回值和处理异常的特点,以及创建Callable线程的流程。此外,还简单比较了Runnable和Callable的差异和适用场景。

Runnable:接口,定义了抽象方法run()。

实现Runnable接口创建多线程的步骤:(最本质创建线程方法)

1)自定义类实现Runnable接口,在类中实现run()方法

2)创建自定义类的对象。

3)创建线程Thread对象,并把自定义类对象作为构造器参数闯入。

4)通过线程Thread对象调用start()方法,启动线程,运次run()方法。

说明:

1)如果通过自定义类继承Thread方式实现多线程,自定义类重写run(),然后创建自定义类对象调用start(),进而调用了run()。

2)Thread类本身实现了Runnable接口,Thread类自然实现了抽象方法run(),如下:

@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

target是Runnable接口实现类的对象:
public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

3)Thread类是实现了Runnable接口的,而我们自定义类实现了Runnable接口和其抽象方法run(),创建了自定义类对象后还把其作为Thread构造器参数传入,就是因为上面的Thread方法。

    

Callable:接口,定义抽象方法call(),此方法有返回值,异常机制。

实现Callable接口创建多线程的步骤;

1)创建一个实现callable接口的实现类,在此实现类中实现call(),把线程需要执行的操作声明在其中。

2)创建上面实现类对象,并把此对象作为FutureTask类构造器参数,创建FutureTask类对象

3)创建Thread类对象,把FutureTask对象作为构造器参数传入,然后调用start()

说明:

1)Runnable和Callable是同一级别,两者都有各自抽象函数:run()和call(),后者函数更强大,因为有返回值、可以抛出异常和支持泛型。

2)FutureTask实现了RunnableFuture接口;RunnableFuture接口继承Runnable接口。代码如下:

public class FutureTask<V> implements RunnableFuture<V>

public interface RunnableFuture<V> extends Runnable, Future<V> 

FutureTask间接实现了Runnable接口。

3)待续。。

 

创建多线程的第三种方法:继承Thread类:

1)创建类继承thread类,并具体实现run()方法

2)创建上面类的对象,通过对象调用start():开启新线程,执行run()方法体

<think>好的,我现在需要回答用户关于JavaRunnableCallable接口区别的问题。首先,我要回顾一下用户提供的引用内容,确保准确理解两者的不同点。根据引用[1]、[2]、[3]、[4]、[5],RunnableCallable的主要区别包括返回值、异常处理与FutureTask的结合使用。 首先,Runnable的run方法没有返回值,而Callable的call方法可以返回结果。这点在引用[3][5]中提到,特别是Callable可以通过FutureTask获取返回值。接下来是异常处理,Runnable不能抛出受检异常,只能在内部处理,而Callable可以抛出异常,由调用方捕获。引用[5]提到这一点,并且还说明了FutureTask.get()会阻塞主线程直到任务完成。 然后,我需要考虑它们的应用场景。比如,Runnable适合不需要返回结果的任务,而Callable适用于需要返回结果或抛出异常的情况,如引用[2][3]中的例子所示。此外,FutureTask不仅可以包装Callable,还能包装Runnable,如引用[4]中的构造函数所示,这可能涉及到结果的处理方式不同。 用户可能还关心如何在实际代码中使用这两个接口,比如使用Lambda表达式简化代码,如引用[1]中的示例。同时,线程池的使用可能也是相关点,但用户的问题主要集中在区别上,所以暂时不需要深入线程池的部分。 接下来,我需要组织这些信息,按照用户要求的结构清晰回答,分点说明区别,并结合引用中的代码示例。同时,生成相关问题时要覆盖接口设计、异常处理、返回值获取方法以及实际应用选择因素等方面。 最后,确保所有LaTeX格式正确,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能涉及较少数学公式,更多是代码文字描述。需要检查是否有遗漏的关键点,比如Callable与FutureTask的关系,以及Runnable如何通过FutureTask包装来传递结果,如引用[4]中的第二个构造函数所示。 总结:回答应包括五个主要区别点,每个点都结合引用中的信息,并附上代码示例说明,最后生成相关问题引导用户深入理解。</think>### JavaRunnableCallable接口的区别 #### 1. **返回值** - **Runnable**:`run()` 方法无返回值,适用于不需要返回结果的任务。 ```java Runnable task = () -> System.out.println("执行任务"); ``` - **Callable**:`call()` 方法返回泛型结果(如 `Integer`、`String` 等),需通过 `FutureTask` 获取返回值[^3][^5]。 ```java Callable<Integer> task = () -> 123; FutureTask<Integer> future = new FutureTask<>(task); new Thread(future).start(); System.out.println(future.get()); // 输出 123 ``` #### 2. **异常处理** - **Runnable**:无法抛出受检异常,只能在内部通过 `try-catch` 处理[^5]。 - **Callable**:允许抛出受检异常,异常会封装到 `FutureTask` 中,调用 `future.get()` 时可捕获 `ExecutionException`[^3][^5]。 #### 3. **接口定义** - **Runnable**:函数式接口仅包含 `run()` 方法。 ```java public interface Runnable { void run(); } ``` - **Callable**:包含泛型返回值的方法 `call()`。 ```java public interface Callable<V> { V call() throws Exception; } ``` #### 4. **与FutureTask的关联** - **Runnable**:若需返回结果,需通过 `FutureTask` 包装并指定结果类型[^4]: ```java Runnable task = () -> System.out.println("任务完成"); FutureTask<String> future = new FutureTask<>(task, "默认结果"); ``` - **Callable**:直接与 `FutureTask` 绑定,通过 `future.get()` 获取返回值[^3][^4]。 #### 5. **线程阻塞** - **Callable**:调用 `future.get()` 会阻塞主线程,直到子线程完成任务并返回结果[^5]。 ```java FutureTask<Integer> future = new FutureTask<>(() -> { Thread.sleep(2000); return 100; }); new Thread(future).start(); Integer result = future.get(); // 主线程在此处阻塞2秒 ``` #### 总结对比表 | 特性 | Runnable | Callable | |---------------------|---------------------------------|-----------------------------------| | 返回值 | 无 | 有(泛型) | | 异常处理 | 需内部处理 | 可抛出受检异常 | | 接口方法 | `void run()` | `V call() throws Exception` | | 与FutureTask结合 | 需包装为`Runnable` + 结果默认值 | 直接通过`Callable`获取返回值 | | 适用场景 | 简单异步任务 | 需返回结果或处理异常的任务 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值