并发编程-Future模式

断了今生、忘了曾经 提交于 2019-11-30 01:13:42

1.Future模式有点类似商品订单。比如在网上进行购物,当看中某一件商品时,就可以提交订单。提交订单完毕在家等候送货上门。卖家根据订单取货、发货,并配送到顾客手中。大部分情况下,卖家处理订单没那么快,可能需要几天时间。而这段时间买家不必再家里等候,可以做其他事情。

将此类推到程序设计中,当某一段程序提交了一个请求,期望得到一个答复。但非常不幸的是,服务程序对这个请求的处理可能非常慢。在传统的单线程环境下,调用函数是同步的,也就是说它必须要等到服务程序返回结果后,才能够进行其他处理。而在Future模式下,调用方式该为异步,而原来等待返回的时间段,在主调用函数中,则可以用于处理其他事物。传统程序的调用流程如下图所示。

                                        图1-1 传统串行程序调用流程

采用Future模式设计程序,调用流程如下。

                                        图1-2 Future模式流程图

                                        表1-3 Future模式的主要参与者


参与者 作用
Main 系统启动,调用Client发出请求你
Client 返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData
Data 返回数据的接口
Future Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData
RealData 真实数据,其构造是比较慢的

2.Future模式的代码实现

2.1Main函数的实现

    main函数主要负责调用Client发起请求,并使用返回的数据:


public static void main(String[] args) {
// TODO Auto-generated method stub


    Client client = new Client();
    Data data = client.request("test");
    System.out.println("----------------------------------");

    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    System.out.println("----------------------------------");
    System.out.println(data.getResult());

}

2.2Client的实现

public class Client {


    public Data request(final String req_name) {

        FutureData fd = new FutureData();

        new Thread() {
        @Override
        public void run() {
        // TODO Auto-generated method stub

        RealData rd = new RealData(req_name);
        fd.setRd(rd);
    
        };
        }.start();

        return fd;

    }
}

2.3Data的实现

public interface Data {


    public String getResult();

}

2.4FutureData的实现

    FutureData实现了一个快速返回的RealData的包装。是RealData的虚拟实现,因此它可以快速的被构造返回。当使用FutureData的getResult()方法时,程序会阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。

/**
 * packed the readdata
 * @author cosco
 *
 */
public class FutureData implements Data {

protected RealData rd = null;

    protected volatile boolean  isReady  = false;

    public RealData getRd() {
        return rd;
    }




    public synchronized void setRd(RealData rd) {

        if(isReady){
            return;
        }

        this.rd = rd;

        isReady = true;

        notifyAll();

    }




    @Override
    public synchronized String getResult() {
    // TODO Auto-generated method stub
    while(!isReady){
    try {
        wait();
       } catch (InterruptedException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
        }
    }

    return rd.getResult();
    }


}


2.5RealData的实现

    RealData是最终需要使用的数据模型,它的构造很慢。在这里,使用sleep()函数模拟这个过程:


package org.cosco.thread;

/**
 * 
 * @author cosco
 *
 */
public class RealData implements Data {
	
	private final String result;

	public RealData(String param){
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < 10; i++){
			sb.append(param);
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
			
		result = sb.toString();
	}
	
	@Override
	public  String getResult() {
		// TODO Auto-generated method stub
		
		return result;
	}

}





3.JDK的内置实现

Future模式比较常用,JDK的并发包中,就已经了一中Future模式的实现。JDK中实现的比较复杂,提供了更为丰富的多线程控制功能。核心结构如图:


                                                图3-1 JDK内置的Future模式

可以使用JDK内置的Future模式实现我们的功能,首先实现Callable接口,实现具体的业务逻辑。


import java.util.concurrent.Callable;

public class RealData implements Callable<String>{
	
	private String param;
	
	public RealData(String param){
		this.param = param;
	}
	
	
	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		
		StringBuffer sb = new StringBuffer();
		
		for(int i = 0; i < 10; i++){
			sb.append(param);
			
			Thread.sleep(100);
			
		}
		return sb.toString();
	}

}

    在这改进中,RealData的构造变得非常快,其业务逻辑被移到call()方法内,并通过call()方法返回。

main方法修改如下:

package testthread02;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class testmain {

	public static void main(String[] args) throws InterruptedException, ExecutionException {

		FutureTask<String> future = new FutureTask<String>(new RealData("a"));

		ExecutorService es = Executors.newFixedThreadPool(1);

		es.submit(future);

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println(future.get());

		es.shutdown();

	}

}


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!