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();

    }

}

运行结果:


与装饰模式的区别:

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

//蓝莓冰淇淋 
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集合为:

在调用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();
        }

运行结果:

 

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);
        }
}

结果:运行超时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值