【Java并发编程学习 8】Callable和Future详解

Callable和Future

什么是Callable

在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储区以及线程通信的方式实现获得任务结果的目的。

不过,Java中,也提供了使用Callable和Future来实现获取任务结果的操作。Callable用来执行任务,产生结果,而Future用来获得结果。

Callable和Runnable源码对比

Callable接口与Runnable接口是否相似,查看源码::
在这里插入图片描述在这里插入图片描述
区别:
Runnable接口,在它里面只声明了一个run()方法:
由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

Callable接口,在它里面也只声明了一个方法,只不过这个方法叫做call():
可以看到,这是一个Callable是一个泛型接口,call()函数返回的类型就是传递进来的V类型。

Callable如何使用

一般情况下是配合ExecutorService来使用的,在ExecutorService接口中声明了若干个submit方法的重载版本:(ExecutorService就是线程池的实现类,上篇章文讲解了详细的线程池):
在这里插入图片描述

看到返回值了吗,返回值都是Future泛型接口

什么是Future

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

三者代码示例:

package com.lijie;

import java.util.concurrent.*;

public class TestMain {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池
        ExecutorService executor = Executors.newCachedThreadPool();

        //给线程池添加Callable线程,并且执行线程,获取线程执行结果
        Future<Integer> future = executor.submit(new TestCallable());

        //get方法获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
        Integer integer = future.get();
        System.out.println("子线程执行结果"+integer);

        // 关闭线程池
        if (executor != null) {
            executor.shutdown();
        }

        //主线程执行
        for (int i = 0; i < 10; i++)
            System.out.println("主线程执行:i==" + i);

    }

}

//实现Callable接口
class TestCallable implements Callable<Integer> {

    public Integer call() throws Exception {
        System.out.println("执行线程");
        Thread.sleep(5000);
        return 5000;
    }

}

Future常用获取结果方法

  1. V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
  2. V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。
  3. boolean isDone() :如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true。
  4. boolean isCanceller() :如果任务完成前被取消,则返回true。
  5. boolean cancel(boolean mayInterruptRunning) :其实就是关闭线程执行的任务:能够中断执行中的任务、判断任务是否执行完成、获取任务执行完成后额结果。
    5.1 如果任务还没开始,执行cancel(…)方法将返回false;
    5.2如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;
    5.3当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;
    5.4当任务已经完成,执行cancel(…)方法将返回false。
    5.5mayInterruptRunning参数表示是否中断执行中的线程。
发布了68 篇原创文章 · 获赞 56 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43122090/article/details/105071017