一、Callable 接口
1、概述
- 目前我们学习了有两种创建线程的方法,一种是通过继承 Thread 类,另一种是
通过实现 Runnable 接口创建线程,但是,Runnable 缺少的一项功能是,当线程
终止时(即 run 方法完成时),无法使线程返回结果,为了支持此功能,Java 中提供了 Callable 接口
2、Callable 接口对比 Runnable 接口
实现 Runnable 接口,需要实现无返回值的 run 方法,实现 Callable 接口,需要实现在有返回值的 call 方法
run 方法不会抛出异常,call 方法会抛出异常
3、实现 Runnable 接口和 Callable 接口
class MyThread1 implements Runnable {
@Override
public void run() {
System.out.println("实现 Runnable 接口");
}
}
class MyThread2 implements Callable<Integer> {
@Override
public 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 {
// Runnable
Thread thread1 = new Thread(new MyThread1(), "AA");
// Callable
FutureTask 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 {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 实现了 Runnable 接口");
}
}
class MyThread2 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + " 实现了 Callable 接口");
return 100;
}
}