代理模式(多线程实现状态监控)

【-1】README
-1.1)本文部分文字描述转自“head first 设计模式”,旨在学习  远程代理对象 的基础知识;
-1.2)多线程实现糖果自动售卖机监控程序为原创;
-1.3)博文最后,转载了代理模式的定义;
-1.4)本文中的代码用到了状态模式中的“糖果自动哦售卖机”的中奖事件,for spec info ,please visit  http://blog.csdn.net/pacosonswjtu/article/details/50986380

【0】需求描述
1)problem+solution:
1.1)problem:问题在于监视器和糖果机在同一个 jvm 上面执行,而售卖机的boss的需求是远程监控糖果售卖机,希望在其桌面上远程监控这些机器。
1.2)solution:所以我们可以不要变化 CandyMachineMonitor , 不要将糖果机交给 monitor,而是将一个远程对象的代理交给他;(干货——引入远程代理)
2)远程代理和本地代表:这是一种对象,活在不同的jvm 堆中(更确切地说,在不同的地址空间运行的远程对象)。本地代表:这是一种可以由本地方法调用的对象,其行为会转发到远程对象中;


【1】远程代理技术相关
1)RMI提供了: 客户辅助对象,称为stub(桩)和服务辅助对象,称为skeleton(骨架);(干货——stub==客户辅助对象, 而skeleton==服务辅助对象)

2)制作远程服务(换句话说,这些步骤将一个普通的对象变成可以被远程客户调用的远程对象)
  • step1)制作远程接口: 远程接口定义出可以让客户远程调用的方法;
  • step2)制作远程实现:为远程接口中定义的远程方法提供真正的实现;
  • step3)其中RMI registry(rmiregistry): rmiregistry如同电话簿,客户可以从中查找到代理的位置;
  • step4)开始远程服务:你必须让服务对象开始运行。你的服务实现类会去实例化一个服务的实例,并将这个服务注册到RMI registry。注册之后,这个访问就可以供客户调用了;
3)制作远程服务(代码实例)
(for downloading source code, please visithttps://github.com/pacosonTang/HeadFirstDesignPattern/tree/master/chapter11_proxyPattern/chapter11_rmi)
3.1)制作远程接口(服务端)
  • step1)扩展Remote;
  • step2)声明所有的方法都会抛出  RemoteException;
  • step3)确定变量和返回值是属于原语类型或可序列化类型: 这不难理解。远程方法的变量必须被打包并通过网络运送,这要靠序列化来完成。如果你使用原语类型,字符串和许多API中定义的类型(包括数组和集合),这都不会有问题。如果你传送自定义的类,就必须保证你的类实现了 Serializable ;
  • // 制作远程接口, 声明所有的方法都会抛出  RemoteException
    public interface MyRemote extends Remote{// 确定变量和返回值是属于原语类型或可序列化类型// String 类型就是可序列化的public String sayHello() throws RemoteException;
    }
3.2)制作远程实现(服务端)
  • step1)实现远程接口:你的访问必须要实现远程接口,也就是客户将要调用的方法的接口;
  • step2)扩展 UnicastRemoteObject:为了要称为远程服务对象,你的对象需要某些远程的功能,最简单的方式就是扩展 UnicastRemoteObject;
  • step3)设计一个不带变量的构造器,并声明为 RemoteException: 你的超类UnicastRemoteObject 带来一个小问题: 它的构造器抛出一个 RemoteException。解决方法是 为你的远程实现声明一个构造器,这样就有了一个声明 RemoteException的地方。
  • // 制作远程实现
    public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{private static final long serialVersionUID = 2494818195984623711L;protected MyRemoteImpl() throws RemoteException {super();}@Overridepublic String sayHello() throws RemoteException {return "every body say, xiao tang tang";}public static void main(String[] args) {try {MyRemote service = new MyRemoteImpl();Naming.rebind("hehe", service);} catch (Exception e) {e.printStackTrace();}}
    }
  • step4)用RMI Registry 注册此服务 : 现在你已经有一个远程服务了,必须让它可以被远程客户调用。你要做的就是将此服务实例化,然后放进RMI registry中。当注册这个实现对象时,RMI 系统其实注册的是stub,因为这是客户真正需要的。注册服务使用了 java.rmi.Naming 类的静态rebind()方法(如上述代码);
3.3)执行rmiregistry: 开启一个终端,启动 rmiregistry;

3.4)启动服务:从哪里启动?可能是从你的远程实现类中的main()方法,也可能是从一个独立的启动类;


4)客户如何取得stub对象?
4.1)客户必须取得stub对象(代理)以调用其中的方法,所以我们就需要 RMI Registry的帮忙。
4.2)客户取得stub对象的steps:
  • step1)客户到RMI Registry中寻找: 
  • step2)RMI Registry返回stub对象:
  • step3)客户调用stub的方法,就像stub 就是真正的访问对象一样;
  • public class MyRemoteClient {public void go() {try {MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/hehe");String s = service.sayHello();System.out.println(s);} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {MyRemoteClient client = new MyRemoteClient();client.go();}
    }
  • 打印结果)

Attention)对于RMI, coders 最常犯的三个错误:
  • A1)忘了在启动远程服务前先启动 rmiregistry;
  • A2)忘了让变量和返回值的类型称为可序列化的类型;
  • A3)忘了给客户提供stub类;
【2】将代理模式应用到糖果自动售卖机的监控系统中(多线程实现监控)
(for download, please visithttps://github.com/pacosonTang/HeadFirstDesignPattern/tree/master/chapter11_proxyPattern/chapter11_proxy)
2.1)创建一个远程接口
// 创建远程服务接口(服务器接口)
public interface CandyMachineRemote extends Remote{int getCount() throws RemoteException;String getLocation() throws RemoteException;State getState() throws RemoteException;
}
2.2)提供该远程接口的实现类
public class CandyMachineProxyServer {public static void main(String[] args) throws RemoteException {CandyMachine machine = new CandyMachine("chengdu", 50);try {Naming.rebind("machine", machine);} catch (MalformedURLException e) {e.printStackTrace();}new Thread(new Runnable() { // 开启一个线程实现client循环投币@Overridepublic void run() {System.out.println("\n\n ====== 下面进入循环测试(中奖率为20%) ======");for (int i = 0; i < 5; i++) {machine.insertQuarter();machine.turnCrank();System.out.println(machine);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();;}
}
2.3)启动rmi registry 注册表服务;
E:\bench-cluster\cloud-data-preprocess\designPattern\src>rmiregistry
2.4)将实现类添加到 注册表服务以便client 获取它;
E:\bench-cluster\cloud-data-preprocess\designPattern\src>java com.designpattern.chapter11_proxy.CandyMachineProxyServer
2.5)编写监控器程序
public class CandyMachineProxyMonitor {CandyMachineRemote remoteMachine;public CandyMachineProxyMonitor(CandyMachineRemote remoteMachine) {this.remoteMachine = remoteMachine;}public void report() {int counter = 0;try {while(true) {System.out.println("round" + (++counter));System.out.println("machine.location = " + remoteMachine.getLocation());System.out.println("machine.count = " + remoteMachine.getCount());System.out.println("machine.state = " + remoteMachine.getState());if(counter == 5) {break;}Thread.sleep(10000);}} catch (Exception e) {e.printStackTrace();}}
}

2.5)client 获取该远程对象,之后,就如一般对象那样使用(client==CEO==桌面监视器);
<pre name="code" class="java">//client
public class CandyMachineProxyMonitorTest {public static void main(String[] args) throws RemoteException {CandyMachineRemote remoteMachine;try {remoteMachine = (CandyMachineRemote) Naming.lookup("rmi://127.0.0.1/machine");CandyMachineProxyMonitor monitor = new CandyMachineProxyMonitor(remoteMachine);monitor.report();} catch (MalformedURLException | NotBoundException e) {e.printStackTrace();}}
}
 
打印结果)




【3】代理模式
3.1)定义:代理模式为另一个对象提供了一个替身或占位符以控制对这个对象的访问;
3.2)使用代理模式创建代表对象:让代表对象控制某对象的访问,被代理的对象可以是远程对象、创建开销大的对象或 需要安全控制的对象;


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章搞定面试中的二叉树

转载自 IOExceptioner 算法与数据结构 在上一篇介绍二叉树&#xff08; Android面试题算法之二叉树 、红黑树详细分析&#xff0c;看了都说好&#xff09;&#xff0c;没看的读者建议先去了解了解&#xff0c;接下来再给大家带来一篇关于二叉树的文章。 最近总结了一些数据结…

清洁代码_清洁单元测试

清洁代码编写使用JUnit和某些模拟库的“单元测试”测试很容易。 即使测试甚至不是单元测试并提供可疑的价值&#xff0c;它们也可能产生使某些涉众满意的代码覆盖范围。 编写单元测试&#xff08;在理论上是单元测试&#xff0c;但是比基础代码更复杂&#xff09;因此也很容易编…

jvm(6)-Class字节码文件结构总结

【0】README 0.1&#xff09;本文总结于 Clas字节码文件&#xff0c;旨在理清 Class字节码文件的大体结构&#xff1b; 【1】干货开始 对上图的分析&#xff08;Analysis&#xff09;&#xff1a;A1&#xff09;offset0 A1.1&#xff09;头四个字节为CAFEBABE&#xff1a;表示…

Android面试题算法之二叉树

转载自 qing的世界 程序员小乐文章目录 前言二叉树的递归&#xff08;深度优先&#xff09;处理二叉树的层序处理(广度优先)总结“一、前言今年可谓是跌宕起伏的一年&#xff0c;幸好结局还算是圆满。开年的时候由于和公司CTO有过节&#xff0c;被"打入冷宫"&#…

java 读取 文本块_Java文本块

java 读取 文本块文本块是JDK增强建议&#xff08; JEP 355 &#xff09;&#xff0c;可以在JDK 13和14中用作预览语言功能。它计划在JDK 15中成为永久性功能。文本块是跨越多行并且不需要的String文字。对于大多数转义序列。 动机 在标准Java字符串中嵌入XML&#xff0c;JSON…

代理模式之虚拟代理(仅了解)

【0】README0.1&#xff09;本文全文转自 “head first 设计模式”&#xff0c;旨在了解 虚拟代理动态代理&#xff1b;0.2&#xff09;晚辈我 java.swing 烂到渣&#xff0c;没有写出干货荔枝&#xff0c;抱歉&#xff1b;【1】虚拟代理简述1&#xff09;远程代理&#xff1a;…

红黑树详细分析

转载自 coolblog 算法与数据结构“一、红黑树简介红黑树是一种自平衡的二叉查找树&#xff0c;是一种高效的查找树。它是由 Rudolf Bayer 于1972年发明&#xff0c;在当时被称为对称二叉 B 树(symmetric binary B-trees)。后来&#xff0c;在1978年被 Leo J. Guibas 和 Robert…

rest api如何创建_REST:创建资源

rest api如何创建资源创建是常见的REST API操作。 在这篇文章中&#xff0c;我们将看到如何创建单个资源。 客户要求 通常&#xff0c;通过将POST请求发送到父集合资源来创建资源。 这将使用新生成的ID创建一个新的下属资源。 例如&#xff0c;对/ projects的POST请求可用于在…

java字节码指令简介(仅了解)

【0】README0.1&#xff09;本文全文转自 “深入理解jvm”&#xff0c; 旨在了解 java字节码指令 的基础知识&#xff1b;【1】写在前面1&#xff09;由于jvm 采用面向操作数栈而不是寄存器的结构&#xff0c;所以大多数的指针都不包含操作数&#xff0c;只有一个操作码&#x…

什么是 CAS 机制

转载自 永远爱大家的 程序员小灰示例程序&#xff1a;启动两个线程&#xff0c;每个线程中让静态变量count循环累加100次。最终输出的count结果是什么呢&#xff1f;一定会是200吗&#xff1f;加了同步锁之后&#xff0c;count自增的操作变成了原子性操作&#xff0c;所以最终…

java xmpp_Java XMPP负载测试工具

java xmpp在本文中&#xff0c;我们将开发用Java编写的XMPP负载测试工具。 目录 1.简介 2. XMPP负载测试工具 3.先决条件 4. LoadXmppTest Java程序 4.1。 创建一个新的Maven项目 4.2。 创建主类 4.3。 XmppManager类 4.4。 建立 4.5。 负载测试 5.总结 6.参考 7.下载Maven项目…

jvm(7)-虚拟机类加载机制

【0】README0.1&#xff09;本文转自“深入理解jvm”&#xff0c;旨在学习 虚拟机类加载机制 的基础知识&#xff1b;【1】概述1&#xff09;类加载机制&#xff1a;虚拟机把描述类的数据从Class 文件加载到内存&#xff0c;并对数据进行校验&#xff0c;转换解析和初始化&…

什么是CAS机制?(进阶篇)

转载自 永远爱大家的 程序员小灰 这一期我们来深入介绍之前遗留的两个问题&#xff1a; Java当中CAS的底层实现 CAS的ABA问题和解决方法 首先看一看AtomicInteger当中常用的自增方法 incrementAndGet&#xff1a; public final int incrementAndGet() {for (;;) {int cur…

c++ 前缀 变量命名_前缀命名

c 前缀 变量命名如果您是第一次查看Takes或Cactoos的源代码&#xff0c;很可能会像其他命名约定一样被命名约定触发&#xff0c;这意味着大多数类名都有两个字母的前缀&#xff1a; BkSafe &#xff0c; RqFake &#xff0c; RsWithStatus &#xff0c; TkGzip等。 老实说&…

jvm(8)-虚拟机字节码执行引擎

【0】README0.1&#xff09;本文转自 “深入理解jvm”&#xff0c;旨在学习 虚拟机字节码执行引擎 的基础知识&#xff1b;【1】概述1&#xff09;物理机和虚拟机的执行引擎&#xff1a; 物理机的执行引擎是直接建立在处理器&#xff0c;硬件&#xff0c;指令集和操作系统层面上…

什么是大数据

转载自 玻璃猫 程序员小灰大数据是具有海量、高增长率和多样化的信息资产&#xff0c;它需要全新的处理模式来增强决策力、洞察发现力和流程优化能力。Big data is high volume, high velocity, and/or high variety information assets that require new forms of processing…

java 记录考勤记录_Java 14:记录

java 记录考勤记录Java 14是在几周前问世的&#xff0c;它引入了Record类型&#xff0c;它是一个不变的数据载体类&#xff0c;旨在容纳一组固定的字段。 请注意&#xff0c;这是一种预览语言功能 &#xff0c;这意味着必须使用--enable-preview标志在Java编译器和运行时中显式…

漫画:什么是HashMap

转载自 玻璃猫 程序员小灰众所周知&#xff0c;HashMap是一个用于存储Key-Value键值对的集合&#xff0c;每一个键值对也叫做Entry。这些个键值对&#xff08;Entry&#xff09;分散存储在一个数组当中&#xff0c;这个数组就是HashMap的主干。 HashMap数组每一个元素的初始值都…

jvm(10)-早期(编译期)优化

【0】README 0.1&#xff09;本文部分文字描述转自 “深入理解jvm”&#xff0c;旨在学习 早期&#xff08;编译期&#xff09;优化 的基础知识&#xff1b; 0.2&#xff09;本文部分文字描述转自&#xff1a; http://www.cnblogs.com/zhouyuqin/p/5223180.html 【1】概述 …

etl介绍与etl工具比较_ETL万岁

etl介绍与etl工具比较提取转换负载是从一个数据系统中提取数据并加载到另一个数据系统中的过程。 涉及的数据系统称为源系统和目标系统。 来自源系统的数据形状与目标系统不匹配&#xff0c;因此需要进行一些转换以使其兼容&#xff0c;该过程称为Transformation 。 转换是由m…