Callable接口
先看看Callable接口的源码:
Callable是一个函数式接口,此时就可以用lambda表达式更简洁地使用它。Callable是个泛型接口,只有一个方法call,该方法返回类型就是传递进来的V类型。call方法还支持抛出异常.
与Callable对应的是Runnable接口,实现了这两个接口的类都可以当做线程任务递交给线程池执行,Runnable接口的源码如下:
Runnable和Callable的区别:
- Runnable接口里执行线程任务是在run方法里写的,Callable接口里执行线程任务是在call方法里写;
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值得;
- call方法可以抛出异常,run方法不可以;
- 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用ExecutorService的submit方法;
- 运行Callable任务可以拿到一个Future对象,表示异步计算的结果.Future对象封装了检查计算是否完成、可取消任务的执行,检索计算的结果的方法;
Further接口
Further接口的源码如下:
- Future是一个接口,代表了一个异步计算的结果。接口中的方法用来检查计算是否完成、等待完成和得到计算的结果。
- get()方法 : 当计算完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。
- cancel()方法 : 如果想取消,那么调用cancel()方法,但如果计算完了,就不能调用cancel方法了。
- isCanceled()方法 : 检查任务是否被取消成功了.
- isDone()方法 : 检查任务是否完成 。
FutureTask类
- Future是一个接口,FutureTask是Future接口的唯一实现类,一般用的时候向上转型,使用Future。
- FutureTask类实现的是RunnableFuture接口.
- 该接口继承了Runnable接口和Future接口,因此FutureTask类既可以当做线程任务递交给线程池执行,又能当Callable任务的计算结果。
- FutureTask可以用来包装Callable或者Runnbale对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以被提交给Executor
Callable的两种实现方法
一.使用FutureTask实现
- 创建一个类,如MyCallableTask,实现Callable接口。
- 在MyCallableTask类中重写call()方法,定义线程需要执行的操作。
- Callable接口的call()方法可以有返回值,并且能够抛出异常。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//定义实现Callable接口的的实现类重写call方法。
public class MyCallableTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
//TODO 线程执行方法
return -1;
}
}
public class Test7 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建Callable对象
Callable<Integer> mycallabletask = new MyCallableTask();
//开始线程
FutureTask<Integer> futuretask = new FutureTask<Integer>(mycallabletask);
new Thread(futuretask).start();
//通过futuretask可以得到MyCallableTask的call()的运行结果:
futuretask.get();
}
}
二.使用线程池实现
举两个例子:
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException,TimeoutException{
//创建一个线程池
ExecutorService executor = Executors.newCachedThreadPool();
//使用submit()方法来执行线程,此处使用的是lambda表达式
Future<String> future = executor.submit(()-> {
TimeUnit.SECONDS.sleep(5);
return "CallableTest";
});
System.out.println(future.get());
executor.shutdown();
}
}
public class CallableAndFuture {
public static void main(String[] args) {
Random random = new Random();
//创建一个线程池
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<Integer> future = threadPool.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return random.nextInt(10000);
}
});
try {
Thread.sleep(3000);
System.out.println(future.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}