标签:
详细参见葛一名老师的《Java程序性能优化》
Futrue模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。
在多线程中经常举的一个例子就是:网络图片的下载,刚开始是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。而在这个过程中可以做一些其他的事情。
首先客户端向服务器请求RealSubject,但是这个资源的创建是非常耗时的,怎么办呢?这种情况下,首先返回Client一个FutureSubject,以满足客户端的需求,于此同时呢,Future会通过另外一个Thread 去构造一个真正的资源,资源准备完毕之后,在给future一个通知。如果客户端急于获取这个真正的资源,那么就会阻塞客户端的其他所有线程,等待资源准备完毕。
公共数据接口,FutureData和RealData都要实现。
1 public interface Data { 2 public abstract String getContent(); 3 }
FutureData,当有线程想要获取RealData的时候,程序会被阻塞。等到RealData被注入才会使用getReal()方法。
1 package com.volshell.future; 2 3 public class FutureData implements Data { 4 5 protected RealData realData = null; 6 protected boolean isReady = false; 7 8 @Override 9 public synchronized String getResult() { 10 // TODO Auto-generated method stub 11 while (!isReady) { 12 try { 13 wait(); 14 } catch (Exception e) { 15 // TODO: handle exception 16 } 17 } 18 return realData.result; 19 } 20 21 public synchronized void setRealData(RealData realData) { 22 if (isReady) 23 return; 24 this.realData = realData; 25 isReady = true; 26 notifyAll(); 27 } 28 }
真实数据RealData
1 package com.volshell.future; 2 3 public class RealData implements Data { 4 protected String result; 5 6 public RealData(String para) { 7 StringBuffer sb = new StringBuffer(); 8 for (int i = 0; i < 10; i++) { 9 sb.append(para); 10 try { 11 Thread.sleep(100); 12 } catch (Exception e) { 13 // TODO: handle exception 14 } 15 result = sb.toString(); 16 } 17 } 18 19 @Override 20 public String getResult() { 21 // TODO Auto-generated method stub 22 return result; 23 } 24 25 }
客户端程序:
1 package com.volshell.future; 2 3 public class Client { 4 public Data request(final String request){ 5 final FutureData future = new FutureData(); 6 new Thread(){ 7 public void run() { 8 9 RealData reaData = new RealData(request); 10 future.setRealData(reaData); 11 }; 12 }.start(); 13 return future; 14 } 15 }
调用者:
1 package com.volshell.future; 2 3 public class Main { 4 public static void main(String[] args) { 5 Client client = new Client(); 6 Data data = client.request("name"); 7 System.out.println("请求完毕!!"); 8 try { 9 Thread.sleep(2000); 10 } catch (Exception e) { 11 // TODO: handle exception 12 } 13 System.out.println("获取的数据:" +data.getResult()); 14 } 15 }
调用者请求资源,client.request("name"); 完成对数据的准备
当要获取资源的时候,data.getResult() ,如果资源没有准备好isReady = false;那么就会阻塞该线程。直到资源获取然后该线程被唤醒。
标签:
原文地址:http://www.cnblogs.com/plxx/p/4574141.html