一 .入门
相信大家使用过线程,对future应该不会陌生吧! 在java一种最简单的使用是Callable,比如:
public class A implements Callable<String> { @Override public String call() throws Exception { return "aaa"; } }
@org.junit.Test public void test3() throws ExecutionException, InterruptedException { ExecutorService service = Executors.newSingleThreadExecutor(); Future<String> restult = service.submit(new A()); System.out.println(restult.get()); }
这样结果就输出了
aaa
很简单吧,现在来简单讲解下future的使用。
二. 理解future
future模式是一种异步获取结果的方式
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); //任务取消 boolean isCancelled(); //判断是否取消 boolean isDone(); //是否已经做完 V get() throws InterruptedException, ExecutionException; //获取值 V get(long timeout, TimeUnit unit) //带超时的获取值 throws InterruptedException, ExecutionException, TimeoutException; }
feture的使用一般使用线程池来获取值。
现在来简单梳理一下调用逻辑
线程池一般都会继承ExecutorService,最终会执行到ThreadPoolExecutor的execute方法,之后利用BlockingQueue来获取值。它里面用的是Condition的await和signal方法。由于对象的await和notify方法和它们类似。那本篇主要使用await和notify来实现future的功能。
三.future 代码实现
public interface IData { //定义数据接口
RealData getResult();
}
public class RealData implements IData { //定义 private String data; public RealData(String name) { try { TimeUnit.SECONDS.sleep(2); //模仿耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } data = "init finish!" + name; //赋值 } @Override public RealData getResult() { return this; } public String getData() { //返回最后添加的值 return data; } }
public class FutureData implements IData { //futureData 实现类 private RealData realData = null; public void setRealData(RealData realData) { this.realData = realData; synchronized (this) { //同步代码块 notifyAll(); //通知所有阻塞线程 } System.out.println("值设置成功!"); } @Override public RealData getResult() { try { synchronized (this) { //同步代码块 wait(); // 阻塞,如果值执行完,由notify唤醒 } } catch (InterruptedException e) { e.printStackTrace(); } return realData; } }
public class FutureClint { public FutureData init(String result) { //使用线程的方式初始化值 FutureData futureData = new FutureData(); new Thread(new Runnable() { @Override public void run() { RealData realData = new RealData("result"); futureData.setRealData(realData); } }).start(); return futureData; //这里是异步返回的 } }
@org.junit.Test public void futureDataTest() throws InterruptedException { FutureClint futureClint = new FutureClint(); FutureData data = futureClint.init("future test"); System.out.println("get data"); System.out.println("result:"+data.getResult().getData()); }
结果
get data //这里结果输出之后应该会等2秒,
值设置成功!
result:init finish!result //异步通知,这里的值会输出
四.总结
需要使用到对象的await和notify方法,以及线程,实现方法有点类似静态代理模式,又有点策略模式的影子。先需要初始化一个真实的对象,然后在线程里面讲这个对象赋值给future对象,这样就可以直接返回future对象,在输出future对象的属性值时,需要通知当前阻塞的线程往下执行!