模仿FutureTask模式
一、定义Callable接口
/**
* @author fangjianfeng
* @version 1.0
* @date 2021/5/22 8:16
*/
public interface MyCallable<String> {
String call();
}
二、实现Callable接口
/**
* @author fangjianfeng
* @version 1.0
* @date 2021/5/22 8:17
*/
public class MyCallableImpl<V> implements MyCallable<String>{
@Override
public String call() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "调用完成";
}
}
三、定义FutureTask类
import java.util.concurrent.locks.LockSupport;
/**
* @author fangjianfeng
* @version 1.0
* @date 2021/5/22 8:23
*/
public class MyFutureTask<V> implements Runnable{
//通过构造器注入Callable
private MyCallable myCallable;
private V result;
private Thread currentThread;
public MyFutureTask(MyCallable myCallable) {
this.myCallable = myCallable;
}
@Override
public void run() {
result = (V)myCallable.call();
//获取到结果唤醒阻塞的主线程
LockSupport.unpark(currentThread);
}
public V get(){
//结果不为空直接返回
if(result != null){
return result;
}
//没有获取到结果记录当前线程,并阻塞当前线程
currentThread = Thread.currentThread();
LockSupport.park(currentThread);
return result;
}
}
四、测试
/**
* @author fangjianfeng
* @version 1.0
* @date 2021/5/22 8:33
*/
public class Test {
public static void main(String[] args) {
MyFutureTask<String> stringMyFutureTask = new MyFutureTask<String>(new MyCallableImpl());
new Thread(stringMyFutureTask).start();
String s = stringMyFutureTask.get();
System.out.println(s);
}
}
五、总结
FutureTask因为是需要新开线程去执行,所以需要去实现Runable接口,在实现的run方法中通过调用从构造函数注入的Callable接口的call方法来获取返回结果。主线程调用get方法,如果没有获取到结果则当前线程调用LockSupport.park方法阻塞线程并记录当前线程,待run方法中call方法调用完成之后释放记录的阻塞状态的主线程,主线程继续执行返回result结果。