JUC并发编程快速入门篇(五)—— Callable&Future 接口

Callable 和 Future 接口

Callable接口

Callable 接口实现多线程的特点如下(重点)

  1. 为了实现 Runnable,需要实现不返回任何内容的 run()方法,而对于Callable,需要实现在完成时返回结果的 call()方法。简而言之Runnable接口没有返回值,Callable接口有返回值

  2. call()方法可以引发异常,而 run()则不能。

  3. 为实现 Callable 而必须重写 call 方法

  4. 不能直接替换 runnable,因为 Thread 类的构造方法根本没有 Callable

//创建新类 MyThread 实现 runnable 接口
class MyThread implements Runnable{
    @Override
    public void run() {
    }
}
//新类 MyThread2 实现 callable 接口
class MyThread2 implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
    return 200;
    }
}

Callable&FutureTask实现多线程

常用方法

public boolean cancel(boolean mayInterrupt): 用于停止任务。如果尚未启动,它将停止任务。如果已启动,则仅在 mayInterrupt 为 true时才会中断任务。

public Object get()抛出 InterruptedException,ExecutionException: 用于获取任务的结果。如果任务完成,它将立即返回结果,否则将等待任务完成,然后返回结果。

public boolean isDone(): 如果任务完成,则返回 true,否则返回 fals

案例

//实现Callable接口
class MyThread2 implements Callable{

    @Override
    public Integer call() throws Exception {
        return 2;
    }
}
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //Runnable方式创建线程
        new Thread(new MyThread1(),"线程一").start();

        //Callable方式创建线程
//        new Thread(new MyThread2(),"线程二").start();  //错误写法

        //FutureTask
        //FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());

        //lam表达式简化
        FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
            System.out.println(Thread.currentThread().getName()+"come in callable");
           return 1024;
        });

        //FutureTask<Integer> futureTask3 = new FutureTask<>(() -> 1024);

        //创建线程
        new Thread(futureTask2,"线程二").start();

        while (!futureTask2.isDone()){ //1.任务未完成输出 wait
            System.out.println("wait");
        }

        //调用FutureTask的get方法
        System.out.println(futureTask2.get());//2.任务完成 输出1024

        System.out.println(Thread.currentThread().getName()+"come over"); //主线程over
    }
}

FutureTask

Java 库具有具体的 FutureTask 类型,该类型实现 Runnable 和 Future,并方便地将两种功能组合在一起。 可以通过为其构造函数提供 Callable 来创建FutureTask。然后,将 FutureTask 对象提供给 Thread 的构造函数以创建Thread 对象。因此,间接地使用 Callable 创建线程。

核心原理:(重点)

在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业单开一个线程交给 Future 对象在后台完成

  • 当主线程将来需要时,就可以通过 Future 对象获得后台作业的计算结果或者执行状态
  • 一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
  • 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法
  • 一旦计算完成,就不能再重新开始或取消计算
  • get 方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常
  • get 只计算一次,因此 get 方法放到最后
posted @ 2021-12-23 23:37  转身刹那的潇洒  阅读(195)  评论(0编辑  收藏  举报