首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Guava源码分析——Proxy形式(TimeLimiter)

2013-09-30 
Guava源码分析——Proxy模式(TimeLimiter)代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用

Guava源码分析——Proxy模式(TimeLimiter)
代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用。主要解决的问题是:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

Guava源码分析——Proxy形式(TimeLimiter)

interface Image {

    public void displayImage();

}


class RealImage implements Image {

    private String filename;

    public RealImage(String filename) {

        this.filename = filename;

        loadImageFromDisk();

    }


    private void loadImageFromDisk() {

        System.out.println("Loading   " + filename);

    }


    public void displayImage() {

        System.out.println("Displaying " + filename);

    }

}


class ProxyImage implements Image {

    private String filename;

    private Image image;


    public ProxyImage(String filename) {

        this.filename = filename;

    }

    public void displayImage() {

        if(image == null)

            image = new RealImage(filename);

        image.displayImage();

    }

}


class ProxyExample {

    public static void main(String[] args) {

        Image image = new ProxyImage("MyPhoto");

        image.displayImage();

    }

}

运行结果:

Guava源码分析——Proxy形式(TimeLimiter)

与装饰模式的区别:

装饰模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们通常在一个代理类中创建一个对象的实例。当我们使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造,例如:

//蓝莓冰淇淋 
AbstractIceCream blueberryIceCream = new BlueberryAdapter(new IceCream()); 

//蓝莓巧克力冰淇淋
AbstractIceCream bb_ch_iceCream = new BlueberryAdapter(new ChocolateAdapter(new IceCream())); 

//加3层巧克力
AbstractIceCream lot_of_chocolate_iceCream = new ChocolateAdapter(new ChocolateAdapter(new ChocolateAdapter(new IceCream())));

 

 

在Guava的TimeLimiter类中就应用到了代理模式:

   TimeLimiter:用于对某一类对象的所有方法运行时间进行限制,即在给定时限内方法正常执行,否则抛出异常。该类生成一个代理,当调用被代理的对象的方法时,会强制加一个时间限制。定义了 newProxy(T target, Class<T> interfaceType, long timeoutDuration, TimeUnit timeoutUnit) 和 callWithTimeOut(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean interruptible)。

 

1、 newProxy()方法生成 target的一个代理

注意:参数interfaceType必须为接口类型。

在该方法中,首先会找出接口的interruptible方法:

  Set<Method> set = Sets.newHashSet();    for (Method m : interfaceType.getMethods()) {      if (declaresInterruptedEx(m)) {        set.add(m);      }    }

这里会判断接口的每一个方法是否抛出InterruptedException异常,如果没有抛出,则不会加到interruptible方法集合里。

例如上面得到的Method集合为:

Guava源码分析——Proxy形式(TimeLimiter)

在调用callWithTimeout时, 该集合用来判断,调用的方法是否amInterruptible。

以判断应该调用future.get(timeoutDuration, timeoutUnit); 或Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit);来获取执行结果。

 

下面例子中,将直接使用上面代理模式中定义的类:

  TimeLimiter limiter = new SimpleTimeLimiter();        Image image = new ProxyImage("MyPhoto");        Image proxy = limiter.newProxy(image, Image.class, 1000, TimeUnit.MILLISECONDS);        try {            proxy.displayImage();        } catch (Exception e) {            e.printStackTrace();        }

运行结果:

Guava源码分析——Proxy形式(TimeLimiter)

 

2、 callWithTimeout()方法:如果 callable执行完毕时还没有到达限定时间则将结果或异常传给调用者,否则抛出 UncheckedTimeoutException。用法如下:

public class TimeLimiterTest {        public static void main(String[] args){            SimpleTimeLimiter simpleTimeLimiter = new SimpleTimeLimiter();            String hello = null;            try {                hello = simpleTimeLimiter.callWithTimeout(new Callable<String>(){                    @Override                    public String call() throws Exception {                        return "Hello";                    }}, 100, TimeUnit.MILLISECONDS, true);            } catch (Exception e) {                e.printStackTrace();            }            System.out.println(hello);             String word = null;            try {                word = simpleTimeLimiter.callWithTimeout(new Callable<String>(){                    @Override                    public String call() throws Exception {                        Thread.sleep(100);                        return "Word";                    }}, 99, TimeUnit.MILLISECONDS, true);            } catch (Exception e) {                e.printStackTrace();            }            System.out.println(word);        }}

结果:运行超时

Guava源码分析——Proxy形式(TimeLimiter)

热点排行