Future表示一个可能还没有完成的异步任务的结果,也可以理解为获取未来执行结果的票据,通过这个票据可以获取异步任务的结果。但是有可能异步任务还没执行结束,这时候你就要等着,这就是为说明调用future.get()的时候,调用线程会陷入阻塞的原因。
下面我们自己来模拟实现一个future吧
public interface Future<T> {
T get() throws InterruptedException;
}
public class AsynFuture<T> implements Future<T> {
private boolean done = false;
private T result;
@Override
public T get() throws InterruptedException {
synchronized (this){
while (!done){
this.wait();
}
}
return result;
}
public void done(T result) {
synchronized (this){
this.result=result;
this.done = true;
this.notifyAll();
}
}
}
public interface FutureTask<T> {
T call();
}
public class FutureService {
public <T>Future<T> submit(FutureTask<T> task){
AsynFuture<T> asynFuture = new AsynFuture();
//开一个新的线程去执行这个task
new Thread(()->{
T result=task.call();//去执行这个task
asynFuture.done(result);//执行完后将这个结果返回通知
}).start();
return asynFuture;
}
public <T>Future<T> submit(FutureTask<T> task, Consumer consumer){
AsynFuture<T> asynFuture = new AsynFuture();
//开一个新的线程去执行这个task
new Thread(()->{
T result=task.call();//去执行这个task
asynFuture.done(result);//执行完后将这个结果返回通知
consumer.accept(result);
}).start();
return asynFuture;
}
}
public class Client {
public static void main(String[] args) throws InterruptedException {
FutureService service =new FutureService();
Future<String> future = service.submit(new FutureTask<String>() {
@Override
public String call() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "finish";
}
});
System.out.println("主线程do other things ======");
String s = future.get();
System.out.println(s);
}
}
主线程submit一个异步任务之后依然可以做别的事,但是当主线程调用future.get()的时候会被阻塞,直到10秒之后才能拿到异步任务结果,解除阻塞状态。
也可以submit一个异步任务的时候注册一个consumer用于消费异步任务结果
public class Client {
public static void main(String[] args) throws InterruptedException {
FutureService service =new FutureService();
Future<String> future = service.submit(new FutureTask<String>() {
@Override
public String call() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "finish";
}
}, new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
System.out.println("主线程do other things ======");
}
}
结果也是一样,10秒后异步任务会调用consumer的accept方法来消费异步结果。