JUC学习之Callable

一、简介

Callable接口,其实跟Runnable接口的使用差不多,只不过Callable接口可以有返回值,返回结果并可能引发异常的任务。但是,Runnable不返回结果,也不能抛出checked异常。

二、源码

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

Callable接口是一个函数式接口,实现Callable接口必须实现call()方法,该方法有一个返回值。

三、示例

多线程的创建方式除了使用Runnable接口,继承Thread类之外,还可以实现Callable接口。但是需要借助一下FutureTask类:

可见,FutureTask实现了RunnableFuture接口,而RunnableFuture接口又是从Runnable接口继承过来的。

主要构造方法:可以传入Callable实现类接口。

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

下面,我们使用Callable接口创建线程:

public class T02_Callable {
    public static void main(String[] args) {
        FutureTask<Integer> futureTask = new FutureTask<>(new TestCallable());
        new Thread(futureTask).start();
        Integer result = null;
        try {
            //get方法会阻塞直到结果准备好
            result = futureTask.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("result = " + result);
    }
}

/**
 * 实现Callable,并指定方法返回值类型为Integer泛型
 * 1. 方法有返回值
 * 2. 可以抛出异常throws Exception
 */
class TestCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

运行结果:

result = 5050

四、总结

Callable 和 Runnable接口的区别:

  • Callable必须实现的方法是call(),Runnable必须实现的方法是run();
  • Callable接口在线程执行完后可以有返回值,Runnable接口并没有;
  • Callable接口可以抛出异常,Runnable接口不可以抛出异常;
发布了220 篇原创文章 · 获赞 93 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/104523759
今日推荐