首页 > 代码库 > 多线程之Future模式

多线程之Future模式

  对于多线程,当A线程需要获得B线程的处理结果,而B线程处理业务需要很长时间,这时候A线程如果一直等待B线程的处理结果,线程A才能继续往下执行代码,这种方式在效率不是很好。所以,这种场景可以使用多线程的Future模式。

  Future模式,就是当A线程需要B线程的处理结果,启动B线程,然后A线程继续往下走,而不必一直等待B线程的结果,当A线程需要用到B线程的结果时候再去获取结果,如果B线程还没处理好业务逻辑,则A线程一直处于阻塞状态。直到B线程处理完成。下面总结一下Future模式的实现方式。

  首先客户端向服务器请求,但是这个资源的创建是非常耗时的,这种情况下,首先返回Client一个FutureSubject,以满足客户端的需求,同时,Future会通过另外一个Thread 去构造一个真正的资源,资源准备完毕之后,在给future一个通知。如果客户端急于获取这个真正的资源,那么就会阻塞客户端的其他所有线程,等待资源准备完毕。

  公共数据接口,FutureData和RealData都要实现

public interface Data {

    public abstract String getConent();
}
public class FutureData implements Data{

    private RealData realData;
    
    private boolean isReady=false;
    
  //进行真实数据的装载
public synchronized void setRealData(RealData realData){ if(isReady) return; isReady=true; this.realData=http://www.mamicode.com/realData; notify(); } //如果业务还没处理完成,则进入阻塞状态 public synchronized String getConent() { while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
    //业务逻辑处理完成,直接返回真实结果
return this.realData.getConent(); } }
public class RealData implements Data{

    private String result;
    //真正处理业务逻辑的方法
    public RealData(String queryStr){
        System.out.println("这是一个很耗时的请求...");
        try {
            Thread.sleep(5000);
        } 
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("操作完毕,获取结果");
        result="查询结果";
    }
    
    public String getConent() {

        return result;
    }

}
public class FutureClient {
    //处理客户端的请求
    public Data request(final String queryStr){
    
final FutureData futureDate =new FutureData();
     //开启一个新的线程去处理复杂的业务逻辑
new Thread(new Runnable() { public void run() { RealData realData=new RealData(queryStr);
         //处理完成对数据进行装载 futureDate.setRealData(realData); } }).start();
     //返回给客户端
return futureDate; } }
public class TestFuture {

    public static void main(String[]args){
        FutureClient fc=new FutureClient();
        Data data=fc.request("查询条件..");
        System.out.println("请求发送成功!");
        System.out.println("做其他的事情...");
        String result = data.getConent();
        System.out.println(result);
        
    }
}

  在JDK1.5 Concurrent 中,提供了这种Callable和Future。Callable产生结果,Future拿到结果。 代码如下:

public class Task implements Callable<String> {

    public String call() throws Exception {

        Thread.sleep(5000);
        
        return "Hello Future";
    }
}

  首先处理业务逻辑的类必须实现Callable接口,他与runable接口的区别是,runable接口重写的Run方法没有返回值,而Callable接口可以定义返回值。

public class FutureDemo {

    public static void main(String[]args) throws InterruptedException, ExecutionException{
        
         System.out.println("已经提交资源申请");
         
         ExecutorService executor=Executors.newCachedThreadPool();
         
         Task task =new Task();
         
         Future<String> future=executor.submit(task);
         
         System.out.println("继续做其他事情...");
         
         if(!future.isDone()){
             System.out.println("任务还没处理完成.."); 
         }
         System.out.println("获取返回结果:"+future.get());
         
         if(future.isDone()){
             System.out.println("任务处理完成"); 
         }
         executor.shutdown();
    }
}

  使用线程池 ExecutorService executor=Executors.newCachedThreadPool(),调用submit方法开启线程,submit方法与executor方法的区别是,submit可以传入实现Callable或者runable接口类型的参数,而executor只可以传入实现runable接口类型的参数。

多线程之Future模式