代理模式与多线程

目录

静态使用场景--多线程

静态代理优缺点:

动态代理:

         动态代理优缺点:


什么是代理模式?

        代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理模式类似于生活中的中介。

代理模式分为静态代理和动态代理。

       代理模式的三要素:

1、真实对象

2、代理对象

3、代理对象和真实对象都要实现的接口

静态使用场景--多线程

思考: 为什么开启一个新线程使用的是start()方法而不直接使用run()方法呢?

public class Demo01 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new RImpl());
        t1.start(); 
    }



class RImpl implements Runnable{
    @Override
    public void run() {
        System.out.println("RImpl的run方法");
    }
}

接下来对源码分析

  • Thread 源码的相关内容如下:
public class Thread implements Runnable {

    public Thread(Runnable target) {      // Thread t1 = new Thread(new RImpl());
        this(null, target, "Thread-" + nextThreadNum(), 0);
    }
    
    public synchronized void start() {
        start0();
    }

    private native void start0();

    @Override
    public void run() {       
        if (target != null) {  //构造器中 : target = new RImpl()
            target.run();
        }
    }
}
  • 先看Thread类中的start()方法,下面是去除了多余部分的源码。实际上创建一个线程靠的是本地方法 start0(),它是c/c++写的涉及操作系统的方法。

public synchronized void start() {    //  t1.start();
        start0();         
//private native void start0(); 本地方法,由jvm调用,和操作系统相关,由它来创建一个线程    
}
  • 再看Thread类中的run方法:它实际上是在start0()创建新线程之后被调用的, target = new RImpl() , 因此实际上调用System.out.println("RImpl的run方法"); 的还是 RImpl的实例对象自己,这就是一个真实的对象。
  •  Thread t1 = new Thread(new RImpl()); 中 t1 就是一个代理对象,它实际上就是一个增强的作用。
  @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
  •  还需要注意的是:调用start0之后线程的状态是RUNNABLE,并不代表线程立马执行

 

静态代理优缺点:

优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。

缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。

 

动态代理:

在动态代理中我们不需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建。

案例:

 

public class Demo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        @SuppressWarnings("all")  // 压制警告
        List obj = (List<String>) Proxy.newProxyInstance(
                Demo.class.getClassLoader(),
                new Class[]{List.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //Object proxy ,不能使用,因为代理对象调用任何方法都会执行上面invoke,造成递归
                        //Object[] args 方法的参数
                        long start = System.currentTimeMillis();
                        
                        if (method.getName().equals("remove")) {
                            System.out.println("发现remove方法,进行拦截");
                            return null;  //remove方法的返回值是String ,所以返回值为null
                        }
                        
                        Object ret = method.invoke(list, args);
                        
                        long end = System.currentTimeMillis();
                        System.out.println(method.getName()+" " + (end - start));  //方法增强,输出程序运行的时间
                        return ret;
                    }
                }
        );
        //代理对象调用方法,先把代理对象强转成ArrayList 否则无法调用方法
        obj.add("刘备");
        obj.add("张飞");
        obj.add("关羽");
        obj.add("刘备");
        obj.remove(3);
        System.out.println(list);
    }
}

 

动态代理优缺点:

优点:相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。可以对某些功能进行拦截或者增强。

缺点:仅支持interface代理

应用场景:支付功能后的短信发送

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值