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());   }       }


 2.1.4装饰者模式
      装饰者模式可以有效分离性能组件和功能组件,从而提升模块的可维护性并增加模块的复用性。
      装饰者(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
原创粉丝点击