一、Callable 接口
1、概述
- 目前我们学习了有两种创建线程的方法,一种是通过继承 Thread 类,另一种是
通过实现 Runnable 接口创建线程,但是,Runnable 缺少的一项功能是,当线程
终止时(即 run 方法完成时),无法使线程返回结果,为了支持此功能,Java 中提供了 Callable 接口
2、Callable 接口对比 Runnable 接口
-
实现 Runnable 接口,需要实现无返回值的 run 方法,实现 Callable 接口,需要实现在有返回值的 call 方法
-
run 方法不会抛出异常,call 方法会抛出异常
3、实现 Runnable 接口和 Callable 接口
class MyThread1 implements Runnable {@Overridepublic void run() {System.out.println("实现 Runnable 接口");}
}class MyThread2 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("实现 Callable 接口");return 100;}
}
4、Callable 实现线程创建问题
-
Thread 类的构造器不支持接收 Callable 实现
-
需要寻找一个类,既和 Runnable 接口有关,又和 Callable 接口有关
-
FutureTask 类满足条件,该类实现了 Runnable 接口,构造器支持接收 Callable 实现
二、FutureTask 类
1、构造器
- 创建一个 FutureTask 对象,一旦运行就执行 Callable 实现
public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW;
}
- 创建一个 FutureTask 对象,一旦运行就执行 Runnable 实现,并安排成功完成时 get 方法返回给定的 result
public FutureTask(Runnable runnable, V result) {this.callable = Executors.callable(runnable, result);this.state = NEW;
}
2、常用方法
方法 | 说明 |
---|---|
get() | 获取结果 |
boolean isDone() | 判断是否执行完毕 |
3、基本使用
package com.my.callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {// RunnableThread thread1 = new Thread(new MyThread1(), "AA");// CallableFutureTask futureTask1 = new FutureTask(new MyThread2());FutureTask<Integer> futureTask2 = new FutureTask(() -> {System.out.println(Thread.currentThread().getName() + " 实现了 Callable 接口");return 200;});FutureTask<Integer> futureTask3 = new FutureTask<Integer>(new MyThread1(), 300);Thread thread2 = new Thread(futureTask1, "BB");Thread thread3 = new Thread(futureTask2, "CC");Thread thread4 = new Thread(futureTask3, "DD");// 开启线程thread1.start();thread2.start();thread3.start();thread4.start();Thread.sleep(1000);// isDone 方法System.out.println(futureTask1.isDone());System.out.println(futureTask2.isDone());System.out.println(futureTask3.isDone());// get 方法System.out.println(futureTask1.get());System.out.println(futureTask2.get());System.out.println(futureTask3.get());}
}class MyThread1 implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " 实现了 Runnable 接口");}
}class MyThread2 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println(Thread.currentThread().getName() + " 实现了 Callable 接口");return 100;}
}