7 Callable接口
7.1 Callable接口创建线程7.2 FutureTask
7 Callable接口创建线程的多种方式:
- 继承Thread类实现Runnable接口Callable接口线程池
目前学习了有两种创建线程的方法,一种是通过创建 Thread 类,另一种是通过使用 Runnable 创建线程,但是,Runnable 缺少的一项功能是,当线程终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能,Java 中提供了 Callable 接口
比较Runnable接口和Callable接口
Callable中的call()计算结果,如果无法计算结果,会抛出异常
Runnable中的run()使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用该对象的run方法
总的来说:run()没有返回值,不会抛出异常。而call()有返回值,会抛出异常
因为Thread的构造函数中没有Callable接口的参数设置,直接替换不可以,只能用下面这种线程创建方法(找一个类,即和Runnable接口有关系,又和Callable接口有关系)
发现Runnable接口有实现类FutureTask(中间对象)
FutureTask的构造函数有Callable参数,通过FutureTask创建线程对象
使用 lambda 方式创建代码如下:
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"执行Runnable");
}).start();
FutureTask task = new FutureTask<>(() -> {
System.out.println(Thread.currentThread().getName() + "使用Callable接口");
return "Callable接口返回值";
});
new Thread(task).start();
System.out.println("Callable返回值:" + task.get());
}
}
输出为:
Thread-0执行Runnable Thread-1使用Callable接口 Callable返回值:Callable接口返回值
详细代码可以参考如下代码
//比较 callable和runnable 的区别
class MyThread1 implements Runnable{
@Override
public void run() {
//这里没有返回值
}
}
class MyThread2 implements Callable{
@Override
public Object call() throws Exception {
System.out.println(Thread.currentThread().getName()+"线程运行");
return "Callable 的实现线程"; //有返回值
}
}
public class diffentence {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建 实现Runnable 的线程
new Thread( new MyThread1(),"t1" ).start();
//创建 实现Callable 的线程 不能直接替换 ,没有这个类型的构造方法
// new Thread( new MyThread2(),"t2" ).start();
//选择FutureTask 他是 Runnable 的实现类,而且构造方法含有Callable类型
FutureTask task = new FutureTask(new MyThread2());
new Thread(task,"hhh").start();
System.out.println("返回值"+task.get()); //调用里面的返回值
}
}
7.2 FutureTask
进入FutureTask底层源码可以看到它的构造器
// 创建一个FutureTask,一旦运行就执行给定的Callable public FutureTask(Callablecallable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } // 创建一个FutureTask,一旦运行就执行给定的Ru你那边了,并安排成功完成时get返回给定的结果 public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
其他常用的代码:
// get()获取结果
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
// outcome就是返回值
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
未来的任务,如果运行过一次,那么下一次,就直接得到结果



