Start |
(1)call()方法可以有返回值。
(2)call()方法可以声明抛出异常。
由于Callable接口是Java5新增的接口,而且它不是Runnable接口的子接口,所以就不能作为Thread的target。而且call()方法还有一个返回值,如何获取这个返回值呢?Java5提供了Future接口来代表Callable接口里call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类实现了Future接口,,同时也实现了Runnable接口(可以作为Thread类的target了)
Future 接口定义了如下几个公共方法来控制它关联的Callable任务:
(1)boolean cancel(boolean mayInterruptIfRunning):试图取消该Future里关联的Callable任务。
(2)V get():返回Callable任务里call()方法的返回值。调用该方法将导致程序阻塞,必须等到子线程结束后才会得到返回值。
(3)V get(long timeout,TimeUnit unit):返回Callable任务里call()方法的返回值。该方法让程序最多阻塞timeout和unit指定的时间。如果经过指定时间Callable任务依然没有返回值,将会抛出TimeoutException异常。
(4)boolean isCancelled():如果在Callable任务正常完成前被取消,则返回true。
(5)boolean isDone():如果Callable任务完成,返回true。
How |
(1)创建Callable接口的实现类,并重写该类的call()方法,该call()方法将作为线程执行体,且该call()方法有返回值,再创建Callable实现类的实例。从Java8开始,可以直接使用Lambda表达式创建Callable对象。
(2)使用FutureTask类包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target来创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
Demo |
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//先使用Lambda表达式创建Callable<Integer>对象
//使用FutureTask包装Callable对象
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)()->{
int i =0;
for( ;i < 10;i++){
System.out.println(Thread.currentThread().getName() + "的循环变量i的值:" + i);
}
return i;
});
new Thread(task,"有返回值的线程").start();
System.out.println(task.get());
}
}
End |