多线程与高并发(八):Callable
在Java中,创建线程除了继承Thread类和实现Runnable接口之外,还可以通过实现Callable接口创建线程。
一、如何通过实现Callable接口创建线程
public class MyThread implements Callable<Object> {
@Override
public Object call() throws Exception {
return "this is my thread";
}
}
二、Callable与Runnable的区别
1、Callable可以有返回值。
2、Callable可以抛出异常。
三、如何使用Callable
1、Future接口
由于实现Callable接口可以有返回值,但返回值是通过异步计算而得到的,那么该如何得到call方法的返回值呢?为此,可以使用Future接口,顾名思义,它可以保存call方法在未来计算出的返回值。
首先了解Future的几个方法:
cancel(boolean):用来停止一个任务,如果任务可以停止(通过入参来进行判断),则返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false。
get:用于获取call方法返回的结果,如果任务完成,它将立即返回结果,否则等待
isDone:如果任务完成返回true,否则返回false。
2、FutureTask
FutureTask实现了RunnableFuture接口,相当于实现了Future接口和Runnable接口。即FutureTask既可以执行也可以保存结果。
如何使用FutureTask:
① 通过Thread.start执行call方法:
由于FutureTask实现了Runnable接口,故可以使用Thread.start(Runnable task)开启线程执行call方法。
public class CallableDemo implements Callable<String> {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(1);
return "callable";
}
public static void main(String[] args) {
// 构造FutureTask FutureTask(Callable<V> callable)
FutureTask<String> futureTask = new FutureTask<>(new CallableDemo());
// 执行futureTask
new Thread(futureTask).start();
try {
// 通过get方法获取到异步线程的值
System.out.println(futureTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
② 通过线程池执行call方法:
由于FutureTask实现了Runnable接口,故可以使用ExecutorService.submit(Runnable task)用线程池执行call方法。
public static void main(String[] args) {
// 构造FutureTask FutureTask(Callable<V> callable)
FutureTask<String> futureTask = new FutureTask<>(new CallableDemo());
// 执行futureTask
ExecutorService threadPool = Executors.newSingleThreadExecutor();
threadPool.submit(futureTask);
try {
// 通过get方法获取到异步线程的值
System.out.println(futureTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭线程池
threadPool.shutdown();
}
3、线程池:
可以通过线程池执行Callable的call方法得到返回值。
public static void main(String[] args) {
// 执行futureTask
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(new CallableDemo());
try {
// 通过get方法获取到异步线程的值
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭线程池
threadPool.shutdown();
}
本文地址:https://blog.csdn.net/sinat_32144323/article/details/114274289