1 引入
比如说我们调用一些方法的的时候,这个方法执行的时间比较长,如果是同步调用的化的就会调用方就会因为这个被调用方阻塞。
比如说我们去定生日蛋糕的时候,我们可以同步等待蛋糕制作完成带走蛋糕,也可以先去处理别的事情比如逛逛周边的商场等,等到差不多的时候回去取蛋糕带走
eg:
package study.wyy.concurrency.future;
public class SyncInvoker {
public static void main(String[] args) throws InterruptedException {
String result = get();
System.out.println(result);
doOther();
}
private static void doOther() {
System.out.println("do other thing....");
}
private static String get() throws InterruptedException {
// 模拟get方法执行的耗时
Thread.sleep(10000L);
return "FINSH";
}
}
main方法只有等到get方法执行完毕才会去执行doOther()
2 Future模式
Future模式简单来说说调用方可以先去处理别的事情,在未来的某个时间去那之前被调用方的结果。
package study.wyy.concurrency.future;
/**
* @Description 封装返回给调用的的结果, 泛型T就是结果
*
* @Author wyaoyao
* @Date 2020/9/6 10:14 下午
* @Param
* @Return
* @Exception
*
*/
public interface Future<T>{
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:32 下午
* @Description: 提供一个方法,让调用方通过这个来拿调用结果
*/
T get() throws InterruptedException;
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:34 下午
* @Description: 当任务执行完毕,将结果通知Future
*/
void done(T result);
}
package study.wyy.concurrency.future;
/**
* @Description: 任务,封装真正的执行的逻辑
* @Author wyaoyao
* @Date 2020/9/6 10:16 下午
* @Param
* @Return
* @Exception
*/
public interface FutureTask<T> {
/**
* @Description 封装真正的执行的逻辑
* @Author wyaoyao
* @Date 2020/9/6 10:16 下午
* @Param
* @Return
* @Exception
*/
T call();
}
package study.wyy.concurrency.future;
/**
* @Description 将Future和FutureTask桥接起来
* @Author wyaoyao
* @Date 2020/9/6 10:18 下午
* @Param
* @Return
* @Exception
*/
public class FutureService {
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:18 下午
* @Description: 提交任务
*/
public <T> Future<T> submit(final FutureTask<T> task){
// new AsyncFuture,返回给调用方
Future<T> future = new AsyncFuture<>();
// 开启一个线程去执行本次的任务(异步)
new Thread(()->{
// 执行逻辑
T result = task.call();
// 执行完毕,通知给future
future.done(result);
}).start();
return future;
}
}
package study.wyy.concurrency.future;
/**
* @Description 异步的实现
* @Author wyaoyao
* @Date 2020/9/6 10:20 下午
* @Param
* @Return
* @Exception
*/
public class AsyncFuture<T> implements Future<T>{
/**
* @Description: 是否已经执行完
*/
private volatile boolean isDone = false;
private T result;
@Override
public T get() throws InterruptedException {
synchronized (this){
while (!isDone){
// 如果还没有完成,外部(调用方)想通过这个方法拿执行结果,肯定是不能让拿的,所以等待
this.wait();
}
}
// 完成的话,就返回结果
return result;
}
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:34 下午
* @Description: 当任务执行完毕,将结果通知Future
*/
@Override
public void done(T result){
synchronized (this){
this.result = result;
this.isDone = true;
// 唤醒线程
this.notifyAll();
}
}
}
package study.wyy.concurrency.future;
public class AsyncFutureTest {
public static void main(String[] args) throws InterruptedException {
FutureService futureService = new FutureService();
Future<String> future = futureService.submit(() -> {
// 模拟方法执行的耗时
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "FINSH";
});
// 干其他事情去了
doOther();
// 其他事情做完了,我来取刚刚的结果(蛋糕)
String result = future.get();
System.out.println(result);
}
private static void doOther() throws InterruptedException {
System.out.println("do other thing....");
// 模拟方法执行的耗时
Thread.sleep(1000L);
}
}
3 总结
角色
- Future: 代表的是未来的一个凭据
- FutureTask:将调用逻辑进行了隔离
- FutureService:桥接Future和FutureTask
4 改进:加入CallBack
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GfuQwPuO-1599899882146)(evernotecid://FA2713E9-40BE-49E5-BF9D-E3ACD77E4128/appyinxiangcom/21741088/ENResource/p599)]
这里完全可以使用java8 提供的consumer这个函数式接口,不需要自己去定义一个接口。
package study.wyy.concurrency.future;
import java.util.function.Consumer;
/**
* @Description 将Future和FutureTask桥接起来
* @Author wyaoyao
* @Date 2020/9/6 10:18 下午
* @Param
* @Return
* @Exception
*/
public class FutureService {
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:18 下午
* @Description: 提交任务
*/
public <T> Future<T> submit(final FutureTask<T> task){
// new AsyncFuture,返回给调用方
Future<T> future = new AsyncFuture<>();
// 开启一个线程去执行本次的任务(异步)
new Thread(()->{
// 执行逻辑
T result = task.call();
// 执行完毕,通知给future
future.done(result);
}).start();
return future;
}
/**
* @author: wyaoyao
* @Date: 2020/9/6 10:18 下午
* @Description: 提交任务
*/
public <T> Future<T> submit(final FutureTask<T> task, Consumer<T> consumer){
// new AsyncFuture,返回给调用方
Future<T> future = new AsyncFuture<>();
// 开启一个线程去执行本次的任务(异步)
new Thread(()->{
// 执行逻辑
T result = task.call();
// 执行完毕,通知给future
future.done(result);
// 执行完毕,交给回调
consumer.accept(result);
}).start();
return future;
}
}
public static void main(String[] args) throws InterruptedException {
FutureService futureService = new FutureService();
Future<String> future = futureService.submit(() -> {
// 模拟方法执行的耗时
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "FINSH";
},s->{
System.out.println(s);
});
// 干其他事情去了
doOther();
}