java程序性能优化---2--2.1常有设计模式

  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 {

	@Test
	public 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;
	@Override
	public Order getOrder(int id) throws RemoteException{ //返回订单信息
	  Order o = new Order();
	  o.setClientName("billy");
	  o.setNumber(20);
	  o.setProductName("desk");
	  return o;
	}
	@Override
	public String getClientName(int id) throws RemoteException{
	  return "billy"; //返回订单的客户名
	}
	@Override
	public String getProdName(int id) throws RemoteException{
	  return "desk"; //返回商品名称
	}
	@Override
	public 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;
       }
     }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值