【-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)使用代理模式创建代表对象:让代表对象控制某对象的访问,被代理的对象可以是远程对象、创建开销大的对象或 需要安全控制的对象;

代理模式(多线程实现状态监控)相关推荐

  1. 多线程中的静态代理模式

    静态代理的例子: 1 /** 2 * 1.真实角色 3 * 2.代理角色 4 * 3.共同实现的接口 5 * @author tele 6 * 7 */ 8 public class StaticPr ...

  2. RocketMQ 5.0:无状态代理模式的探索与实践

    本文作者:金吉祥, Apache RocketMQ PMC Member,阿里云智能高级技术专家 背景 首先,让我们来看下是遇到了哪些痛点问题,促使我们去探索一种无状态代理的RocketMQ新架构的: ...

  3. Java从接触到放弃(十五)--线程、多线程、静态代理模式

    Day Fifteen 线程 多任务: 可以理解为一个人同时去干几件事,就好比在上厕所的时候边大号边玩手机,这就是一个多任务的实例.再好比现在很多人中午在吃饭的时候,或者说在吃饭的时候,看一些下饭综艺 ...

  4. 静态代理模式(多线程底部原理)

    静态代理模式总结(线程底部原理) 真实对象和代理对象都要实现同一个接口 代理对象要代理真实角色 好处: - 代理对象可以做很多真实对象做不了的事情 - 真实对象专注做自己的事情 创建静态代理模式:一个 ...

  5. Java多线程:静态代理模式

    静态代理模式 要求:有真实角色,代理角色 真实角色和代理角色要实现同一个接口 代理角色要持有真实角色的引用 设计静态代理模式 (1)必须有一个共同使用的接口 1 // 共同的接口 2 public i ...

  6. 设计模式之代理模式-05

    代理模式(Proxy) 17.11.1 代码模式的基本介绍 1) 代理模式: 为一个对象提供一个替身,以控制对这个对象的访问 2) 被代理的对象可以是 远程对象. 创建开销大的对象或需要 安全控制的对 ...

  7. 服务器状态监控之一背景介绍及解决方案建议

    SCOM与SCVMM 一.背景介绍 XXX公司是一家外商独资企业,主要致力于高品质零售商用地产的投资.开发和管理,其在国内大部分一线及部分二级城市都有分公司或是连锁购中心,随着公司业务规模的不断壮大增 ...

  8. 代理模式(Proxy)--静态代理

    1,代理模式的概念 代理模式:为其他对象提供一种代理,以控制对这个对象的访问(代理对对象起到中介的作用,可去掉功能服务或者添加额外的服务) 2,代理模式的分类 (1)远程代理:类似于客户机服务器模式 ...

  9. 设计模式笔记——代理模式

    设计模式笔记--代理模式 代理模式介绍 代理模式通常是介于请求方和提供方的一个中介系统,请求方是发送请求的一方,提供方是根据请求提供相应资源的一方 Web中的代理服务器就是一个例子,客户端向代理服务器 ...

最新文章

  1. 再见Python!Yann LeCun警告:深度学习需要新编程语言
  2. Python——函数 8、可变长参数
  3. openEuler Developer Day 启动大会招募环节,报名通道同步开启!
  4. 美国知名天使投资人列出愿意投资的30大创意方向
  5. 【codevs1048】石子归并
  6. JS正则表达式详解[转]
  7. 如何学好3D游戏引擎编程
  8. Android EditText属性大全
  9. html 右边是iframe 左右结构_HTML iframe 用法总结收藏
  10. 苹果注册开发者账号过程
  11. JS正则匹配实例邮箱、手机号、电话、货币
  12. 企业邮箱客户端怎么选?哪个更好用?
  13. Android-APK瘦身实践
  14. Typecho+Handsome主题美化
  15. 圣思园——Java SE Lesson 4
  16. 万网m3 windows linux切换,万网M3-linux虚拟主机开启网页Gzip压缩方法
  17. 计算机学院运动会搞笑解说词,运动会入场式搞笑解说词
  18. 江苏统考计算机英语作文,2017年高考江苏卷英语作文
  19. 跑鸭”微信小程序-一款基于校园跑步的社交小程序
  20. 多图详解:七种具体方法增强代码可扩展性

热门文章

  1. CF56E Domino Principle 树状数组 + 简单dp
  2. CF1486B Eastern Exhibition
  3. Codeforces Round #746 (Div. 2)
  4. Strategic game(树的最小点覆盖)
  5. Matlab与高等数学
  6. jzoj1281-旅行【dp】
  7. jzoj3169-[GDOI2013模拟4]生产汽车【斜率优化dp,单调队列,二分】
  8. ssl提高组国庆模拟赛【2018.10.7】
  9. JoyOI(TYVJ)1071-LCIS【线性dp,LIS,LCS】
  10. 【dfs】虫食算(ybtoj dfs-1-3)