7 Callable接口
7.1 Callable接口创建线程7.2 FutureTask 7 Callable接口
创建线程的多种方式:
继承Thread类实现Runnable接口Callable接口线程池 7.1 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
输出为:
Thread-0执行RunnableThread-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
进入FutureTask底层源码可以看到它的构造器
// 创建一个FutureTask,一旦运行就执行给定的Callablepublic FutureTask(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);}
未来的任务,如果运行过一次,那么下一次,就直接得到结果