目录
FutureTask案例分析
1.FutureTask代码演示
public class FutureTaskTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Task task = new Task();
//测试FutureTask的阻塞获取结果
FutureTask<Integer> integerFutureTask = new FutureTask<>(task);
Thread thread = new Thread(integerFutureTask);
thread.start();
//此处阻塞获取结果
System.out.println(integerFutureTask.get());
System.out.println("执行完成");
}
}
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
return 100;
}
}
2.FutureTask分析
优点:
FutureTask是可以获取返回结果的一个线程任务,不像Runnable没有返回值,纯后端多线程任务
缺点:
FutureTask的缺点也很明显,因为只有当需要同步返回的时候才会使用这个当做一个target,所以必须要等待线程执行完
才能拿到执行结果,并且会阻塞主线程
FutureTask实现异步回调
1.代码自己实现异步回调功能
public class FutureTaskTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Task task = new Task();
//测试FutureTask的阻塞获取结果
FutureTask<Integer> integerFutureTask = new FutureTask<>(task);
Thread thread = new Thread(integerFutureTask);
thread.start();
ExecutorService executorService = Executors.newFixedThreadPool(10);
FutureTaskTools.callBack(integerFutureTask, new FutureTaskCallBack<Integer>() {
@Override
public Integer getResult(Integer integer) {
System.out.println("执行结果:"+integer);
return integer;
}
},executorService);
System.out.println("执行完成");
}
}
/**
* 处理异步回调的工具类
*/
class FutureTaskTools{
/**
* futureTask的阻塞任务进行异步处理,丢到线程池中执行
* @param futureTask
* @param futureTaskCallBack
* @param executorService
*/
public static void callBack(FutureTask futureTask,FutureTaskCallBack futureTaskCallBack,ExecutorService executorService){
executorService.submit(new FutureResultTask(futureTaskCallBack,futureTask));
}
/**
* 1.将futureTask的get阻塞方法封装为一个异步任务
* 2.调用get成功之后,使用回调函数发生回调
* @param <T>
*/
private static final class FutureResultTask<T> implements Runnable {
private FutureTaskCallBack<T> futureTaskCallBack;
private FutureTask<T> futureTask;
public FutureResultTask(FutureTaskCallBack<T> futureTaskCallBack, FutureTask<T> futureTask) {
this.futureTaskCallBack = futureTaskCallBack;
this.futureTask = futureTask;
}
@Override
public void run() {
try {
//阻塞等待执行结果
T t = futureTask.get();
//回调,将结果反馈到主线程中
futureTaskCallBack.getResult(t);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
/**
* /事件回调接口,异步任务执行完后回调的类型
* @param <T>
*/
interface FutureTaskCallBack<T>{
T getResult(T t);
}
/**
* 待执行的任务
*/
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
return 100;
}
}
2.异步回调原理分析
1.FeatureTask获取结果的时候是阻塞的,直接丢到一个线程池中进行执行,这样可以保证不阻塞主线程,实现异步
2.FeatureTask是有返回结果的,我们需要包装一个回调对象,可以理解为Handler,当异步线程拿到结果,直接调用即可,实现回调
GUAVA实现异步回调
1.引入jar
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
2.使用guava异步回调代码演示
public class FutureTaskTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Task task = new Task();
ExecutorService executorService = Executors.newFixedThreadPool(10);
ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
ListenableFuture<Integer> submit = listeningExecutorService.submit(task);
Futures.addCallback(submit, new FutureCallback<Integer>() {
@Override
public void onSuccess(@Nullable Integer integer) {
System.out.println("执行结果:"+integer);
}
@Override
public void onFailure(Throwable throwable) {
}
},executorService);
System.out.println("执行完成");
}
}
/**
* 待执行的任务
*/
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
return 100;
}
}
3.原理分析
1.guava的实现原理和之前上一个我们自己实现异步回调原理是一样的
2.Futures相当于我们的FutureTaskTools,将需要的阻塞获取结果对象,进行打包为一个异步任务,丢到线程池
3.ListenableFuture相当于FutureTask,用户阻塞获取同步结果,这个对象可以阻塞获取结果
4.FutureCallback相当于FutureTaskCallBack,用于回调,当异步任务执行完,使用的回调对象