java程序性能优化---2--2.1常有设计模式
来源:互联网 发布:贵阳IBM预测大数据 编辑:程序博客网 时间:2024/05/01 10:12
2.1.1单例模式
public class NewSingleton {private NewSingleton() {}private static class NewSingletonHolder {private static NewSingleton instance = new NewSingleton();}public NewSingleton getInstance() {return NewSingletonHolder.instance;}}使用内部类的方式实现单例,既可以做到延迟加载,也不必使用同步关键字,是一种比较完善的方式。
public class SerSingleton implements Serializable {private static final long serialVersionUID = 6978432124038848244L;String name;private SerSingleton() {System.out.println("Singleton is create");name = "SerSingleton";}private static SerSingleton instance = new SerSingleton();public static SerSingleton getInstance() {return instance;}public static void createString() {System.out.println("createString is Singleton");}// 阻止生成新的实例,总是返回当前对象---必须是这个方法名private Object readResolve() {return instance;}}public class SerSingletonTest {@Testpublic void test() throws Exception {SerSingleton s1 = null;SerSingleton s = SerSingleton.getInstance();// 先将实例串行化到文件FileOutputStream fos = new FileOutputStream("SerSingleton.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(s);oos.flush();oos.close();// 从文件读出原有的单例类FileInputStream fis = new FileInputStream("SerSingleton.txt");ObjectInputStream ois = new ObjectInputStream(fis);s1 = (SerSingleton) ois.readObject();Assert.assertEquals(s, s1);}}
2.1.2代理模式
代理模式可以用于多种场合,如用于远程调用的网络代理,考虑安全因素的安全代理等。延迟加载只是代理模式的一种应用场景。
延迟加载的核心思想是:如果当前并没有使用这个组件,则不需要真正的初始化它。使用一个代理对象替代它原来的位置,
只要在真正需要使用的时候,才对它进行加载。
-------------------------------------------------------------------------------------------
public interface IDBQuery{ String request(); //主题接口 } //真实对象,重量级,构造会比较慢 public class DBQuery implements IDBQuery{ public DBQuery(){ try{ Thread.sleep(1000); }catch(InterruptedException e){ e.pringStackTrace(); } } @Override public String request(){return "request string"; } } //代理类,轻量级,创建很快,用于替代DBQuery public class DBQueryProxy implements IDBQuery{ private DBQuery real = null; @Override public String request(){ //在真正需要的时候,才创建真实对象,创建过程可能很慢 if(real == null){ real = new DBQuery(); return real.request(); } } } public class Main{ public static void main(String[] args){ IDBQuery q = new DBQueryProxy();q.request();//在真正使用时才创建真实对象 } } //将代理模式用户实现延迟加载,可以有效地提升系统的启动速速,对改善用户体验有很大的帮助。 ------------------------------------------------------------------------------------- 动态代理,java自带的 代替上面的DBQueryProxy public class JdkDbQueryHandler implements InvocationHandler{ IDBQuery real = null; @Overiride public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{if(real == null){ real = new DBQuery();return real.request();} } public static IDBQuery createJdkProxy(){ IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance( ClassLoader.getSystemClassLoader(),new Class[]{IDBQuery.class},new JdkDbQueryHandler()); return jdkProxy; } } ------------------------------------------------------------------------------------ cglib实现的代理 public class CglibDbQueryInterceptor implements MethodInterceptor{ IDBQuery real = null; @Override public Object intercept(Object arg0,Method arg1,Object[] arg2,MethodProxy arg3) throws Throwable{if(real == null) real = new DBQuery();return real.request(); } public static IDBQuery createCglibProxy(){ Enhancer enhancer = new Enhancer(); enhancer.setCallback(new CglibDbQueryInterceptor());//置顶切入器,定义代理类逻辑 enhancer.setInterfaces(new Class[] {IDBQuery.class}); //指定实现的接口 IDBQuery cglibProxy = (IDBQuery)enhancer.create(); return cglibProxy; } } ----------------------------------------------------------------------------------------- 使用Javassist生成动态代理可以使用两种方式:一种是使用代理工厂创建,另一种通过使用动态代码创建。 代码略,具体用到可以参考网络资源。 结论:就动态代理的方法调用性能而言,CGLIB和Javassist的机遇动态代码的代理都优于JDK自带的动态代理。 此外,JDK的动态代理要求代理类和真实主题都实现同一接口,而另外两个则无此强制要求。 ------------------------------------------------------------------------------------------- Hibernate框架中对实体类的动态代理是代理模式用于延迟加载的经典实现,有兴趣的读者,可以深入研究下。 Hibernate的延迟加载主要有2种:1是属性的延迟加载,2是关联表的延迟加载。
2.1.3享元模式
享元模式是为数不多的,只为提升系统性能而生动的设计模式。它的主要作用就是复用大对象(重量级对象),
以节省内存空间和对象创造时间。
享元模式和对象池的最大不同在于:享元对象是不可相互替代的,它们各自都有各自的含义和用途;而对象池
中的对象都是等价的,如数据库连接池中的数据库连接。
public interface IReportManager{ public String createReport(); } public class FinancialReportManager implements IReportManager{ //财务报表 protected String tenantId = null; public FinancialReportManager(String tenantId){ this.tenantId = tenantId; } @Override public String createReport(){ return "This is a financial report"; } } public class EmployeeReportManager implements IReportManager{ //员工报表 protected String tenantId = null; public EmployeeReportManager(String tenantId){ this.tenantId = tenantId; } @Override public String createReport(){ return "This is a employee report"; } } //最为核心的享元工厂类如下,它是享元模式的精髓所在。 public class ReportManagerFactory{ Map<String,IReportManager> financialReportManager = new HashMap<>(); Map<String,IReportManager> employeeReportManager = new HashMap<>(); IReportManager getFinancialReportManager(String tenantId){IReportManager r = financialReportManager.get(tenantId);if(r==null){ r = new FinancialReportManager(tenantId); financialReportManager.put(tenantId,r);//维护已创建的享元对象}return r; } IReportManager getEmployeeReportManager(String tenantId){ IReportManager r = employeeReportManager.get(tenantId);if(r==null){ r = new EmployeeReportManager(tenantId); employeeReportManager.put(tenantId,r);//维护已创建的享元对象}return r; } } public class Main{ public static void main(String[] args){ ReportManagerFactory rmf = new ReportManagerFactory(); IReportManager rm = rmf.getFinancialReportManager("A"); System.out.println(rm.createReport()); } }
装饰者模式可以有效分离性能组件和功能组件,从而提升模块的可维护性并增加模块的复用性。
装饰者(Decorator)和被装饰者(ConcreteComponment)拥有相同的接口(Componment)。
被装饰者通常是系统的核心组件,完成特定的功能目标。
而装饰者则可以在被装饰者的方法前后,加上特定的前置处理和后置处理,增强被装饰者的功能。
public interface IPacketCreator{ public String handleContent(); //用于内容处理 } public class PacketBodyCreator implements IPacketCreator{ @Override public String handleContent(){ return "构造核心数据,但不包含格式"; } } public abstract class PacketDecorator implements IPacketCreator{ IPacketCreator componment; public PacketDecorator(IPacketCreator componment){ this.componment = componment; } } public class PacketHTMLHeaderCreator extends PacketDecorator{ public PacketHTMLHeaderCreator(IPacketCreator componment){ super(c); } @Override public String handleContent(){ StringBuilder sb = new StringBuilder(); sb.append("<html>"); sb.append("<body>"); sb.append(componment.handleContent()); sb.append("</body>"); sb.append("</html>\n"); return sb.toString(); } } public class PacketHTTPHeaderCreator extends PacketDecorator{ public PacketHTTPHeaderCreator(IPacketCreator componment){ super(componment); } @Override public String handleContent(){ StringBuilder sb = new StringBuilder(); sb.append("Cache-Control:no-cache\n"); sb.append("Date:Mon,31Dec201412:12:12GMT\n"); sb.append(componment.handleContent()); return sb.toString(); } } public class Main{public static void main(String[] args){ IPacketCreator pc = new PacketHTTPHeaderCreator( new PacketHTMLHeaderCreator(new PacketBodyCreator())); System.out.println(pc.handleContent());} }
2.1.5观察者模式
观察者模式可以用于事件监听,通知发布等场合。
可以确保观察者在不使用轮询监控的情况下,及时收到相关消息和事件。
主题接口,是指被观察的对象。
public interface ISubject{ public void attach(IObserver observer); //添加观察者 public void detach(IObserver observer); //删除观察者 public void inform(); } public interface IObserver{ public void update(Event evt);//更新观察者 } public class ConcreteSubject implements ISubject{ Vector<IObserver> observers = new Vector<>(); public void attach(IObserver observer){ observers.addElement(observer); } public void inform(){ Event evt = new Event(); for(IObserver ob:observers){ ob.update(evt); //注意,在这里通知观察者 } } } public class ConcreteObserver implements IObserver{ public void update(Event evt){ System.out.println("observer receives information"); } }
2.1.6Value Object模式
展示层 -- 业务逻辑层 -- 持久层
RMI客户端 -- RMI服务器 --- RDBMS
getClientName
getProdName
getNumber
替换成Value Object模式下,三次交互只要一次网络通信。
getOrder
使用Value Object 模式可以有效减少网络交互次数,提高远程调用方法的性能,
也能使系统接口具有更好的可维护性。
public interface IOrderManager extends Remote{ public Order getOrder(int id) throws RemoteException; //value Object 模式public String getClientName(int id) throws RemoteException;public String getProdName(int id) throws RemoteException;public int getNumber(int id) throws RemoteException; } public class OrderManager extends UnicastRemoteObject implements IOrderManager{ protected OrderManager() throws RemoteException{ super();}private static final long serialVersionUID = -12120130041231254L;@Overridepublic Order getOrder(int id) throws RemoteException{ //返回订单信息 Order o = new Order(); o.setClientName("billy"); o.setNumber(20); o.setProductName("desk"); return o;}@Overridepublic String getClientName(int id) throws RemoteException{ return "billy"; //返回订单的客户名}@Overridepublic String getProdName(int id) throws RemoteException{ return "desk"; //返回商品名称}@Overridepublic int getNumber(int id) throws RemoteException{ return 20; //返回数量} } public class Order implements java.io.Serializable{ private int orderId;private String clientName;private int number;private String productName;//getter setter } //业务逻辑层注册并开启RMI服务器: public class OrderManagerServer{ public static void main(String[] args){ try{ LocateRegistry.createRegistry(1099); //注册RMI端口 IOrderManager usermanager = new OrderManager();//RMI远程对象 Naming.rebind("OrderManager",usermanager); //绑定RMI对象 System.out.println("OrderManager is ready."); }catch(Exception e){ System.out.println("OrderManager Server failed: "+e); }} } 客户端的测试代码如下,它分别展示了使用value object模式封装数据和不使用value object 模式的性能差异: public static void main(String[] args){ try{ IOrderManager usermanager = (IOrderManager)Naming.lookup("OrderManager"); long begin = System.currentTimeMills(); for(int i=0;i<1000;i++){ usermanager.getOrder(i); //Value Object模式 } System.out.println("getOrder spend:"+(System.currentTimeMills() - begin)); begin = System.currentTimeMills(); for(int i=0;i<1000;i++){ usermanager.getClientName(i); //通过多次交互获取数据 usermaneger.getNumber(i); usermanager.getProdName(i); } System.out.println("2 Method call speed:"+(System.currentTimeMills() - begin)); System.out.println(usermanager.getOrder(0).getClientName()); }catch(Exception e){ System.out.println("OrderManager exception:"+e); } }
2.1.7业务代理模式
value Object 模式是将远程调用的传递数据封装在一个串行化的对象中进行传输,
而业务代理模式则是将一组由远程方法调用构成的业务流程,封装在一个位于展示层的代理类中。
比如,如果用户需要修改一个订单,大概步骤:
校验用户;
获取旧的订单信息;
更新订单。
展示层 -- 业务逻辑层 -- 持久层
RMI客户端 RMI服务端 RDBMS
优化前
checkUser
getOrder
updateOrder
优化方案:在展示层和业务逻辑层之间增加一个业务代理层
展示层
updateOrder-->业务代理 -- 业务逻辑层
基于远程调用封装业务逻辑 RMI服务端
checkUser
getOrder
updateOrder
业务代理模式将一些业务流程封装在前台系统,为系统性能优化提供了基础平台。
在业务代理中,不仅可以复用业务流程,还可以视情况为展示组件提供缓存等功能,从而
减少远程方法调用次数,降低系统压力。
一个未使用业务代理模式的展示层实现代码如下: public static void main(String[] args){ try{ IOrderManager usermanager = (IOrderManager) Naming.lookup("OrderManager"); if(usermanager.checkUser(1)){ Order o = usermanager.getOrder(1);//所有的远程调用都会被执行 //当并发量较大时,严重影响性能o.setNumber(10);usermanager.updateOrder(o); //3个usermanager的方法调用 } }catch(Exception e){ System.out.println("OrderManager exception:"+e); } } 而是用来业务代理后,展示层组件可以优化为: public static void main(String[] args){ BusinessDelegate bd = new BusinessDelegate(); Order o = bd.getOrder(11); o.setNumber(11); bd.updateOrder(o); //使用业务代理完成更新订单 } 在业务代理对象BusinessDelegate中,可以增加缓存,从而直接减少远程方法调用次数 public class BusinessDelegate{ IOrderManager usermanager = null; //封装远程方法调用的流程 public BusinessDelegate(){ try{ usermanager = (IOrderManager)Naming.lookup("OrderManager"); }catch(MalformedURLException e){ e.printStackTrace(); }catch(RemoteException e){ e.printStackTrace(); }catch(NotBoundException e){ e.printStackTrace(); } } public boolean checkUserFromCache(int uid){ return true; } public boolean checkUser(int uid) throws RemoteException{ //当前对象被多个客户端共享,可以在本地缓存中校验用户if(!checkUserFromCache(uid)){ return usermanager.checkUser(1);}return true; } public Order getOrderFromCache(int oid){ return null; } public Order getOrder(int oid) throws RemoteException{ //可以在本地缓存中获取订单,减少远程方法调用次数 Order order = getOrderFromCache(oid); if(order==null){ return usermanager.getOrder(oid); } return order; } public boolean updateOrder(Order order) throws Exception{ //暴露给展示层的方法,封装了业务流程if(checkUser(1)){//可能在缓存中执行 Order o = getOrder(1); o.setNumber(10); usermanager.updateOrder(o);}return true; } }
0 0
- java程序性能优化---2--2.1常有设计模式
- java 程序性能优化《第二章》设计优化 2.1善用设计模式 2 代理模式
- java 程序性能优化 记录2(设计模式)
- java 程序性能优化《第二章》设计优化 2.1善用设计模式 1 单例模式
- java程序性能优化之设计优化--设计模式:单例模式(1)
- Java程序性能优化 读书笔记(二)设计模式:单例模式
- Java程序性能优化 读书笔记(三)设计模式:代理模式
- Java程序性能优化 读书笔记(四)设计模式:享元模式
- Java程序性能优化 读书笔记(五)设计模式:装饰者模式
- Java程序性能优化 读书笔记(六)设计模式:观察者模式
- Java程序性能优化 读书笔记(七)设计模式:ValueObject模式
- Java程序性能优化 读书笔记(十)并行设计模式:Future模式
- Java程序性能优化 读书笔记(十一)并行设计模式:Master-Worker模式
- Java程序性能优化 读书笔记(十二)并行设计模式:Guarded Suspension模式
- Java程序性能优化 读书笔记(十三)并行设计模式:不变模式
- Java程序性能优化 读书笔记(十四)并行设计模式:生产者-消费者模式
- JAVA性能优化之设计模式
- Java用享元模式优化程序性能
- 关联规则介绍
- Linux常用命令(三十七) - free
- 杨辉三角形
- Android SDK Manager 超时不翻墙的解决办法
- hdoj 母牛的故事
- java程序性能优化---2--2.1常有设计模式
- android AtionBar
- 【spoj8757】Kmp 概率Dp
- HttpUrlConnection和HttpClient和android-async-http框架的GET和POST请求
- 在mac上出错:No working C compiler found.
- Android 下拉刷新(刷新布局需用ScrollView包裹)
- VBScript 文件操作
- poj 2491 Scavenger Hunt 字符串离散化
- MovieClip.moveTo 方法