并发-9-Callable和Future

我们原来所说的继承Thread或者实现Runnable的方式都无法获得线程的执行结果,除非使用共享变量或者线程通信,我们先看一下Runnable接口的源码:

public interface Runnable{
    public abstract void run(){
    }
}
复制代码

run()的返回值为void,在任务执行完之后没有返回

继承Thread和实现Runnable这两种方式,都无法获得线程执行的结果

Callable可以弥补这一个缺点:

public interface Callable<V>{
    V call() throws Exception
}

复制代码

是一个泛型接口,返回值类型为传入进来的的T类型的值

注意:Callable中方法是call而不是run

使用Callable

一般配合ExecutorService来使用:

其中声明了若干个重载的submit方法

<T> Future<T> submit(Callable<T> task);

<T> Future<T> submit(Runnable task, T result);    //一般不使用

Future<?> submit(Runnable task);
复制代码

Future

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)

        throws InterruptedException, ExecutionException, TimeoutException;

}

复制代码

cancel:取消任务

mayInterruptIfRunning:是否可以取消正在执行的任务

isCancelled:是否成功取消

isDone:是否已经完成

get:获取执行结果,一直等到任务执行完毕才返回,阻塞等待

get(long timeout, TimeUint unit):用来获取执行结果,指定时间内,还没有获取到结果,就返回null

也就是说Future用于异步获取执行结果或取消执行任务提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

FutureTask是Future的唯一实现

public interface RunnableFuture<V> extends Runnbale,Future<V>
    void run()
}

public class FutureTask implements RunnbaleFuture<V>{
    public FutureTask(Callable<V> callable)
    public FutureTask(Runnable runnable,V result)
}

复制代码

可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

这段代码不给答案啦,动手实践感受一下

public class FutureTaskUseDemo {

    public static void main(String[] agrs) throws InterruptedException, ExecutionException {

        ExecutorService executor = Executors.newCachedThreadPool();

        /**
         * 使用FutureTask的Runnable特性
         */
        Thread thread = new Thread(new FutureTask<>(new BoilWater()));
        thread.start();

        /**
         * 使用FutureTask的Callable特性------第一种写法
         */
        FutureTask futureTask = new FutureTask(new BoilWater());
        executor.submit(futureTask);

        out.println("做饭");
        Thread.sleep(2000);
        out.println("饭做好了");

        while (!futureTask.isDone()) {
            out.println("水还没烧开呢");
            Thread.sleep(1000);
        }

        out.println(futureTask.get());

        /**
         * 使用FutureTask的Callable特性------第二种写法
         */
        Future<String> submit = executor.submit(new BoilWater());

        out.println("做饭");
        Thread.sleep(2000);
        out.println("饭做好了");

        while (!submit.isDone()) {
            out.println("水还没烧开呢");
            Thread.sleep(1000);
        }

        out.println(submit.get());

        /**
         * 多个任务同时并行
         */
        CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(executor);
        for (int i = 0; i < 5; i++) {
            final int taskId = i;
            cs.submit(() -> taskId);
        }
        for (int i = 0; i < 5; i++) {
            try {
                out.println(cs.take().get());
            } catch (Exception e) {

            }
        }
    }
}

class BoilWater implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(5000);
        return System.currentTimeMillis() + " 水烧开了";
    }
}
复制代码

猜你喜欢

转载自juejin.im/post/5bc6b343f265da0afc2c2a63