future模式

DK-Future 模式和实现
最近的项目用到了多线程,发现java.util.concurrent.Future蛮好用的。
像平时,写多线程一般使用Thread/Runnable,直接扔给线程池执行就好了。但是遇到了一些需要获取线程执行结果的情况,就需要使用Callable。对于使用Callable的task,ExecutorService执行后会返回一个Future对象来传递执行结果。
那这个Future是怎么存放返回值的呢,这个Future有什么值得使用的地方呢。我查了一下,发现原来还专门有个Future模式。

Future模式

Future模式在请求发生时,会先产生一个Future凭证给发出请求的客户,它的作用就像是Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成(Thread-Per-Message),真正的目标物件生成之后,将之设定至Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。
结合JDK的Future来看,就是你run线程后,你可以把线程的返回值赋给Future并返回一个Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要get这个Future中的线程结果,就会被阻塞直到线程结束。
就相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。
这样有一个好处,就是你把处理任务交给线程并拿到那个future凭证,就可以去干别的事情了(同时线程也在处理),等你真正要用到这个线程返回值的时候再通过future来获取,这样能缩短阻塞的时间。

Demo

接下来,我们看看Future的一个demo,这个例子很简单,就是为表明线程提交处理后,future对象是立即返回的,紧接着“Ready”马上就打印“Give the future”了;而当调用future.get的时候就停下了,“Get the future”迟迟没有打印,被阻塞了,直到线程执行完毕为止。这里我让他睡了3秒钟,能看得更清楚。
public class FutureTest {
	public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("Ready");
        Future strFuture = executor.submit(new TaskTest());
        System.out.println("Give the future");
        
        System.out.println("Get the future : " + strFuture.get());
        System.out.println("End");
        executor.shutdown();
    }

	public static class TaskTest implements Callable {
		@Override
		public String call() throws Exception {
			Thread.sleep(3000);
			return "Hello World!";
		}
	}
}

Simulator

从future的应用能看出来,其实future实现的功能很简单,就是充当一个线程返回结果的寄存器,只是在获取结果的时候,检查线程是否已完成,还在处理则阻塞,否则返回结果。
下面我做了一个future的模拟实现:
首先future作为一个结果寄存器,就需要有个result来存放结果,另外需要一个isFinish来标记线程是否完成。当然我在set()的时候不仅给result赋值,还把isFinish标记成完成,因为一般返回值都在线程结束时赋值的,所以我也这么简化设计了。
测试使用上面的demo,运行结果也是一样的。只是我的这个future没有JDK那个优雅和健壮,那个还整合到ExecutorService,用起来更方便。 
所以,还有请大神们指导,这样的future实现,是不是还有什么漏洞?大笑
public class FutureSimulator {
	private volatile T result;
	private volatile boolean isFinish = false;
	public void set(T result) {
		this.result = result;
		this.isFinish = true;
	}
	public T get() throws InterruptedException {
		while (!isFinish) {
			Thread.sleep(100);
		}
		return result;
	}
	
    public static void main(String[] args) throws Exception {
    	   FutureSimulator future = new FutureSimulator();
        ExecutorService executor = Executors.newCachedThreadPool();
        System.out.println("Ready");
        executor.submit(new FutureTaskTest(future));
        System.out.println("Give the future");

        System.out.println("Get the future : " + future.get());
        System.out.println("End");
        executor.shutdown();
    }
}

class FutureTaskTest extends Thread {
	private FutureSimulator future;
	public FutureTaskTest(FutureSimulator future) {
		this.future = future;
	}

	@Override
	public void run(){
		try {
			Thread.sleep(3000);
			future.set("Hello World!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值