文章参考 Future 详解
1. Future?异步?
在线程池中,我们知道调用future.get()方法是会阻塞当前线程,知道得到get方法的返回值之后才继续运行,所以future是异步编程?线程池中的提交任务的方法有两种,一个是 execute,参数是 Runnable方法,返回值是 void方法;
第二种方式是 submit方法:
有三种 submit。这三种按照提交任务的类型来算分为两个类型。
提交执行 Runnable 类型的任务。
提交执行 Callable 类型的任务。
但是返回值都是 Future,这才是我们关心的东西。
在submit中可以通过传入参数得到返回值:
示例如下:
public class ThreadPoolExecutorTest {
public static void main(String[] args) throws Exception {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
AtomicInteger atomicInteger = new AtomicInteger();
Future<AtomicInteger> future = executor.submit(() -> {
System.out.println("测试");
//在这里进行计算逻辑
atomicInteger.set(5201314);
}, atomicInteger);
System.out.println("future的内容:" + future.get());
Thread.currentThread().join(); //防止主线程退出
}
}
其中调用的 get()方法是阻塞的,描述可得:
所以总结一下这种场景下返回的 Future 的不足之处:
只有主动调用 get 方法去获取值,但是有可能值还没准备好,就阻塞等待。
任务处理过程中出现异常会把异常隐藏,封装到 Future 里面去,只有调用 get 方法的时候才知道异常了。
2. Guava 中的 Future
增加了一个监听方法,执行完成后通知!!!
public static void main(String[] args) throws InterruptedException {
// 1. 初始化executor
ListeningExecutorService executor = MoreExecutors.listeningDecorator(
Executors.newCachedThreadPool());
// 2. 要执行的任务
ListenableFuture<String> listenableFuture = executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了,好了我叫你。");
TimeUnit.SECONDS.sleep(5);
return "化妆完毕!!";
});
// 3. 设置监听器函数执行回调
listenableFuture.addListener(() -> {
try {
System.out.println(Thread.currentThread().getName()+"-future的内容:" + listenableFuture.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}, executor);
// 主线程任务,不会被阻塞
System.out.println(Thread.currentThread().getName()+"-等女神化妆的时候可以干点自己的事情。");
Thread.currentThread().join();
}
另一种实现方法 FutureCallback 方式:
public class JDKThreadPoolExecutorTest {
public static void main(String[] args) throws Exception {
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture<String> listenableFuture = executor.submit(() -> {
System.out.println(Thread.currentThread().getName()+"-女神:我开始化妆了,好了我叫你。");
TimeUnit.SECONDS.sleep(5);
return "化妆完毕了。";
});
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String result) {
System.out.println(Thread.currentThread().getName()+"-future的内容:" + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println(Thread.currentThread().getName()+"-女神放你鸽子了。");
t.printStackTrace();
}
});
System.out.println(Thread.currentThread().getName()+"-等女神化妆的时候可以干点自己的事情。");
Thread.currentThread().join();
}
}
JDK1.8的CompletableFuture
/**
* JDK1.8 提供的用于异步编程, 类似于流编程
*/
public static void testJDK8CompletableFuture(){
CompletableFuture<Serializable> serializableCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了,好了我叫你。");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "妆化好了";
// 处理异常
}).handleAsync((result, exception) -> {
if (exception != null) {
System.out.println(Thread.currentThread().getName() + "-女神放你鸽子了!");
return exception.getCause();
} else {
return result;
}
}).thenApplyAsync((returnStr) -> {
System.out.println(Thread.currentThread().getName() + "-" + returnStr);
return returnStr;
});
System.out.println(Thread.currentThread().getName() + "-等女神化妆的时候可以干点自己的事情。");
}