一、Callable介绍
1.1 Runnable介绍
Runnable是一个接口,里面声明了run方法。但是由于run方法返回值类型为void,所以在执行完成任务后,无法返回任何结果。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
1.2 Callable介绍
callable位于java.util.concurrent包下,它是一个接口,这个接口下面只有一个call()方法。它是一个泛型接口,可以有返回值,也可以抛出异常
public interface Callable<V> {
V call() throws Exception;
}
二、怎么使用Callable?
2.1 借助FutureTask执行
2.1.1 Future介绍
Future是一个接口,它可以对于具体的Runnable获取Callable任务的执行结果进行取消,查询是否完成,获取结果。必要时可以通过get()方法获取执行结果,该方法会阻塞直到任务返回结果。
2.1.2 Future源码解析
package java.util.concurrent;
public interface Future<V> {
/**
* 用来取消任务,如果取消任务成功,就返回true,如果失败,就返回false
* @param mayInterruptIfRunning 表示是否取消正在执行却没有执行完毕的任务,如果设置了ture,则表示可以
* 取消正在执行过程中的任务
* 如果任务正在执行,若mayInterruptIfRunning为ture,则返回true,若mayInterruptIfRunning为ture为false
* 不会取消任务,返回false,如果任务还没有执行,不管若mayInterruptIfRunning为ture还是false,都返回ture
* 如果任务已完成,则无论不管若mayInterruptIfRunning为ture还是false,一定返回false
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 如果此任务在正常完成之前被取消,则返回true
*/
boolean isCancelled();
/**
* 如果此任务完成,则返回true
*/
boolean isDone();
/**
* 等待任务完成,然后返回其结果,是一个阻塞的方法
*/
V get() throws InterruptedException, ExecutionException;
/**
* 如果在指定的时间内,还没有获取到结果,则返回null
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
2.1.3 总结
- Future能够判断任务是否完成
- Future能够中断任务执行
- Future获取任务执行结果
2.1.3 FutureTask介绍
- 由于Future是一个接口,无法用来直接创建对象使用,所以我们在使用过程中一般都是通过FutureTask来进行实现
- FutureTask类实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable和Future接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable返回值。
- FutureTask可以用来包装Callable或者Runnable对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以提交给Executor
2.1.4 FutureTask三种状态
- 未启动:创建了FutureTask对象,但FutureTask.run()还未执行之前
- 已启动:FutureTask对象的run启动并执行过程中
- 已完成:FutureTask正常结束,或者FutureTask执行被取消(FutrueTask对象的cancel方法),或者FutureTask对象run方法执行抛出异常导致中断而结束,FutureTask都处于已完成的状态
2.2.1 Callable使用案例
Callable使用方式有两种,一种是通过线程池,一种是线程直接调用
线程池介绍和线程池工具类代码
线程池工具类_java线程池工具类-CSDN博客
public class MyCallable implements Callable{
@Override
public Object call() throws Exception {
System.out.println("开始对0—100和计算");
int sum = 0;
for (int i = 0;i < 101; i++) {
sum = sum + i;
}
return sum;
}
}
public class MyCallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
System.out.println("----------------利用线程池进行调用---------------------");
Future<Integer> future = ThreadPoolUtils.submit(myCallable);
System.out.println(future.get());
System.out.println("-----------------new Thread调用FutureTask------------------------");
FutureTask futureTask = new FutureTask(myCallable);
new Thread(futureTask).start();
System.out.println("new Thread调用:"+futureTask.get());
System.out.println("-----------------run调用FutureTask------------------------");
FutureTask<Integer> futureTask2 = new FutureTask<Integer>(()->{
int sum = 0;
for (int i = 0;i < 101; i++) {
sum = sum + i;
}
return sum;
});
futureTask.run();
System.out.println("run调用:"+futureTask.get());
}
}
2.2.2 执行结果
参考文档:FutureTask详解-CSDN博客
JAVA多线程—Callable详解_callable java-CSDN博客