Java随笔-Callable与FutureTask

概述

之前在Java随笔-线程创建中指出线程创建方式只有两种:Thread扩展类、Runnable实现类,并没有把Callable与FutureTask算成一种,也没有解释原因,本文就说明一下为什么通过Callable与FutureTask创建线程不能算一种。

使用

public class CallableDemo {

    private static class CallableUse implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            // 再次输出当前线程名称
            System.out.println(Thread.currentThread().getName());
            System.out.println("这是callable的实现");
            Thread.sleep(1000);
            System.out.println("线程睡了1000ms后callable的实现");
            return 11;
        }
    }

    public static void main(String[] args) {
        // 输出当前线程名称
        System.out.println(Thread.currentThread().getName());

        CallableUse callableUse = new CallableUse();
        FutureTask<Integer> futureTask = new FutureTask<>(callableUse);
        // 开启线程
        new Thread(futureTask).start();

        try {
            // 输出返回值 
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

结果输出:

main
Thread-0
这是callable的实现
线程睡了1000ms后callable的实现
11
结束

创建步骤:

  1. 创建Callable实现类,并指定泛型,即返回值类型。
  2. 以Callable实现类实例为参数创建FutureTask实例,同样需要指定泛型。
  3. 将FutureTask实例作为Thread参数开启线程。

优势

  1. 通过Callable与FutureTask创建线程,然后调用futureTask.get()可以获取Callable实现类的返回值。
    请添加图片描述
    使用Thread和Runnable时,run方法是没有返回值的,若是需要拿到结果还需通过其他方式,而Callable的call() 是可以直接返回结果。
  2. 异步。通过futureTask.get()获取返回值时,即使call()中 Thread.sleep(1000),依然会等所有事情处理完成后再返回结果。此时会该线程会阻塞主线程,等该线程完成后,主线程才会继续执行,而Thread和Runnable线程中阻塞后并不影响主线程执行。

不算新的启动线程方式原因

通过Callable与FutureTask启动线程是Runnable启动线程的一种。

  1. Callable和Runnable基本一致。
@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;
}

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
  1. FutureTask是Runnable的一种。
    首先FutureTask实现类RunnableFuture。
public class FutureTask<V> implements RunnableFuture<V> {...}

然后RunnableFuture实现了Runnable。

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

注:Java中接口可以多继承。

  1. Thread构造中没有FutureTask参数。
    请添加图片描述
    Thread构造有很多,但是没有以FutureTask为参数的,但使用时可以像使用Runnable那样使用,故FutureTask是Runnable是一种。

综上所诉,通过Callable与FutureTask创建线程是实现Runnable接口创建线程中的一种方式,所以通过Callable与FutureTask创建线程不算是新的创建线程方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值