【JUC并发编程07】Callable接口

本文介绍了如何使用Java的Callable接口创建线程,以及FutureTask的作用。Callable允许线程有返回值并可能抛出异常,FutureTask作为Runnable与Callable的桥梁,展示了如何通过FutureTask来实现Callable功能并获取结果。
摘要由CSDN通过智能技术生成

7 Callable接口

创建线程的多种方式:

  1. 继承Thread类
  2. 实现Runnable接口
  3. Callable接口
  4. 线程池

7.1 Callable接口创建线程

目前学习了有两种创建线程的方法,一种是通过创建 Thread 类,另一种是通过使用 Runnable 创建线程,但是,Runnable 缺少的一项功能是,当线程终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能,Java 中提供了 Callable 接口

比较Runnable接口和Callable接口

  1. Callable中的call()计算结果,如果无法计算结果,会抛出异常

    1. Runnable中的run()使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用该对象的run方法

总的来说:run()没有返回值,不会抛出异常。而call()有返回值,会抛出异常

因为Thread的构造函数中没有Callable接口的参数设置,直接替换不可以,只能用下面这种线程创建方法(找一个类,即和Runnable接口有关系,又和Callable接口有关系)

发现Runnable接口有实现类FutureTask(中间对象)

FutureTask的构造函数有Callable参数,通过FutureTask创建线程对象

使用 lambda 方式创建代码如下:

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"执行Runnable");
        }).start();
        FutureTask<String> task = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "使用Callable接口");
            return "Callable接口返回值";
        });
        new Thread(task).start();
        System.out.println("Callable返回值:" + task.get());
    }
}

输出为:

Thread-0执行Runnable
Thread-1使用Callable接口
Callable返回值:Callable接口返回值

详细代码可以参考如下代码

//比较 callable和runnable 的区别
class MyThread1 implements Runnable{
    @Override
    public void run() {
        //这里没有返回值
    }
}
class MyThread2 implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName()+"线程运行");
        return "Callable 的实现线程";  //有返回值
    }
}
 
public class diffentence {
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建 实现Runnable 的线程
        new Thread( new MyThread1(),"t1" ).start();
        //创建 实现Callable 的线程 不能直接替换 ,没有这个类型的构造方法
        // new Thread( new MyThread2(),"t2" ).start();
        //选择FutureTask 他是 Runnable 的实现类,而且构造方法含有Callable类型
        FutureTask<String>  task = new FutureTask(new MyThread2());
        new Thread(task,"hhh").start();
        System.out.println("返回值"+task.get()); //调用里面的返回值
    }
}

7.2 FutureTask

进入FutureTask底层源码可以看到它的构造器

// 创建一个FutureTask,一旦运行就执行给定的Callable
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}
// 创建一个FutureTask,一旦运行就执行给定的Ru你那边了,并安排成功完成时get返回给定的结果
public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

其他常用的代码:

// get()获取结果
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
// outcome就是返回值
private V report(int s) throws ExecutionException {
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

未来的任务,如果运行过一次,那么下一次,就直接得到结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_之桐_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值