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>{@Overridepublic 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();}}}