Future的含义
Future就是将来的意思, 在开辟多线程去执行某个方法,我们是不能获取到改方法的返回值,应为线程和线程之间是相互隔离的,各自有各自的时间线, 线程和线程之间的通信一般都是使用锁来进行同步。所以线程与线程之间的配合少不了锁。
那回到这个模式的含义,试想一下需求,比如A线程去开辟B线程执行某个方法,但是A在某个时刻想获取这个方法的返回值,还有一个问题想一想,一般线程执行在java中都是在run方法中,而且这个run方法是没有返回值,并且方法里面一般都只是局部变量,如果没有发生内存逃逸,一般都会被jvm优化成局部变量。毕竟局部变量随着方法执行结束内存就释放了。
所以我们需要一个全局变量 来接收这个方法的返回值, 那问题来了,如果这个方法还没有被B线程执行结束,此时A线程要找个全局变量? 这时候怎么搞?能怎么搞返回null呗,但是有没有这样的需求A来拿的时候必须要拿到返回值,就算拿不到A线程也可以等,🆗 拿不就是需要进行阻塞了嘛,所以需要用到锁。
呃抽象一下,全局变量是不是需要一个统一的类? 我们切命名他为FutureTask
所以现在是不是关系流程图可以出来了:
Future
public interface Future<V> {
V get();
}
Callable
@FunctionalInterface
public interface Callable<T> {
T call() throws InterruptedException;
}
FutureTask
/**
* 将来的任务
* @Author: puhaiguo
* @Date: 2022-07-12 23:45
* @Version 1.0
*/
public class FutureTask<V> implements Future<V>, Runnable {
/*任务是否完成了*/
private volatile boolean flag;
/*任务*/
private Callable<V> callable;
/*目标返回值*/
private V target;
/*目标方法的异常*/
private Exception exception;
public FutureTask(Callable<V> callable) {
this.callable = callable;
}
@Override
public V get() {
try {
synchronized (this) {
while (!flag) {
wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
return target;
}
}
public Exception getException() {
return exception;
}
protected synchronized void set(V target) {
notify();
this.target = target;
this.flag = true;
}
@Override
public void run() {
V res = null;
try {
res = callable.call();
} catch (Exception e) {
this.exception = e;
} finally {
this.flag = true;
set(res);
}
}
}
测试
/**
*
* @Author: puhaiguo
* @Date: 2022-07-13 00:04
* @Version 1.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(
() -> {
TimeUnit.SECONDS.sleep(10);
return "my task yeh";
}
);
Thread thread = new Thread(futureTask);
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
Exception exception = futureTask.getException();
System.out.println(exception.getMessage());
}
}
总结
呃,多线程都是离不开同步,用好线程同步机制,设计出奇妙的模式。