java多线程——静态代理模式

静态代理模式

在 Java 中,静态代理模式是一种常见的设计模式,它可以在不修改目标对象代码的前提下,对目标对象的功能进行增强。在多线程场景下,静态代理模式同样适用,下面将详细介绍 Java 多线程中的静态代理模式。

1. 静态代理模式的基本概念

静态代理模式包含三个主要角色:

  • 抽象主题(Subject):定义了目标对象和代理对象的共同接口,通常是一个接口或抽象类。
  • 真实主题(RealSubject):实现了抽象主题接口,是实际要执行任务的对象。
  • 代理主题(ProxySubject):也实现了抽象主题接口,持有真实主题的引用,在调用真实主题的方法前后可以添加额外的逻辑。

2. 多线程中的静态代理模式示例

下面通过一个简单的多线程示例来演示静态代理模式的使用。假设我们要实现一个线程任务,该任务的功能是打印一段信息,同时在任务执行前后添加一些额外的日志信息。

步骤 1:定义抽象主题接口
// 抽象主题接口
interface Task {
    void execute();
}
步骤 2:定义真实主题类
// 真实主题类,实现 Task 接口
class RealTask implements Task {
    @Override
    public void execute() {
        System.out.println("正在执行任务...");
        try {
            // 模拟任务执行时间
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("任务执行完成。");
    }
}
步骤 3:定义代理主题类
// 代理主题类,实现 Task 接口
class TaskProxy implements Task {
    private Task realTask;

    public TaskProxy(Task realTask) {
        this.realTask = realTask;
    }

    @Override
    public void execute() {
        System.out.println("任务开始前的准备工作...");
        // 调用真实主题的方法
        realTask.execute();
        System.out.println("任务完成后的清理工作...");
    }
}
步骤 4:使用代理主题类创建线程并执行任务
public class StaticProxyInMultithreading {
    public static void main(String[] args) {
        // 创建真实主题对象
        RealTask realTask = new RealTask();
        // 创建代理主题对象,并将真实主题对象传入
        TaskProxy taskProxy = new TaskProxy(realTask);

        // 创建线程并传入代理主题对象
        Thread thread = new Thread(taskProxy::execute);
        // 启动线程
        thread.start();
    }
}

3. 代码解释

  • 抽象主题接口 Task:定义了一个 execute() 方法,该方法是任务执行的核心方法。
  • 真实主题类 RealTask:实现了 Task 接口,具体实现了 execute() 方法,模拟了一个耗时的任务。
  • 代理主题类 TaskProxy:也实现了 Task 接口,持有一个 Task 类型的引用 realTask。在 execute() 方法中,先输出任务开始前的准备信息,然后调用真实主题的 execute() 方法,最后输出任务完成后的清理信息。
  • 主类 StaticProxyInMultithreading:创建了真实主题对象和代理主题对象,将代理主题对象的 execute() 方法作为线程的任务,启动线程执行任务。

上面看不懂没关系,我这里有个简单的例子

我们就以结婚这件事情来分析,首先结婚人是真实主题类,婚礼公司是代理主题类(负责除了结婚外的事情,比如准备现场),那我们的抽象主题接口就是结婚。

注意四个要素:

  1. 接口
  2. 主要人物
  3. 代理人物
  4. 主类(就是放main方法的地方)

其中接口是主要人物和代理人物都要实现的,是主要事件,区别在于主要人物只用实现主要事件,而代理人物可以在重写接口方法的过程中做一些别的事情。

主要事件(结婚):用接口表示

interface Marry {
    void marry();
}

主要人物(结婚人):只用重写结婚,并只写结婚

class Person implements Marry {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public Person() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void marry() {
        System.out.println("今天是"+name+"结婚的日子");
    }
}

代理人物(婚礼公司):负责婚前和婚后的处理,但是结婚期间就是婚礼人进行,即在婚礼公司的重写方法中代用结婚人的重写方法,类似多态

class MarryCompany implements Marry {
    private Marry Marry_Person;
    public MarryCompany(Marry Marry_Person) {
        this.Marry_Person = Marry_Person;
    }
    public MarryCompany() {}

    public Marry getMarry_Person() {
        return Marry_Person;
    }

    public void setMarry_Person(Marry marry_Person) {
        Marry_Person = marry_Person;
    }

    @Override
    public void marry() {
        before(); // 结婚前的操作
        Marry_Person.marry(); // 这里就是婚礼公司调用结婚人的重写
        after(); // 结婚后的操作
    }
    public void before() {
        System.out.println("结婚前准备场景");
    }
    public void after() {
        System.out.println("结婚后善后");
    }
}

完整代码

package com.demo01;

interface Marry {
    void marry();
}
class Person implements Marry {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public Person() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void marry() {
        System.out.println("今天是"+name+"结婚的日子");
    }
}

class MarryCompany implements Marry {
    private Marry Marry_Person;
    public MarryCompany(Marry Marry_Person) {
        this.Marry_Person = Marry_Person;
    }
    public MarryCompany() {}

    public Marry getMarry_Person() {
        return Marry_Person;
    }

    public void setMarry_Person(Marry marry_Person) {
        Marry_Person = marry_Person;
    }

    @Override
    public void marry() {
        before();
        Marry_Person.marry();
        after();
    }
    public void before() {
        System.out.println("结婚前准备场景");
    }
    public void after() {
        System.out.println("结婚后善后");
    }
}
public class staticProxy {
    public static void main(String[] args) {
        Person p = new Person("6<7");
        MarryCompany mc = new MarryCompany(p);
        // 直接调用而不启用多线程
        mc.marry();
//        //使用多线程,创建线程并传入代理主题对象
//        Thread thread = new Thread(mc::marry);
//        // 启动线程
//        thread.start();
    }
}

疑问解答(必看***)

看到这里的伙伴可能会有些疑问,在这里解答一下难懂点:

  1. 文中类似多态的解释:类似多态就是,婚礼公司里有一个接口对象,而且是通过这个接口对象去接受结婚人,是不是类似多态的父类引用指向子类,然后调用的是子类的方法marry()。

  2. 代理的工作:这样的话我们在主类里面是不是先创建结婚人对象,然后把结婚人对象传给婚礼公司,然后婚礼公司在重写marry方法中调用结婚人的marry。

  3. 关于开启多线程:开启的话这个marry方法就在新线程中执行,而主线程继续执行。两个线程同时进行。

  4. 关于如何开启多线程:创建一个Thread对象,将要执行的任务(在这里即是婚礼公司重写的marry方法)给线程,怎么给呢?将实例化对象下的marry方法给线程,类似Thread thread = new Thread(mc::marry),其中mc是婚礼公司,::可以理解为在什么下的,这里就可以翻译成这个线程执行在mc下的marry方法。

  5. 开启与不开启多线程的区别:开启就是新线程与主线程并发执行,不开启就是直接在主线程代用mc的marry方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值