网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.使用SMTP协议发送邮件.
.Java中的排序.
.JAVA入门教程:流控制.
.关于Java中文问题的几条分析原则.
.Java核心代码例程之:DatagramSe.
.[JAVA100例]039、生成PDF文件.
.桌面系统的第二次战役 -- 难解难.
.通过WindowsXPEmbedded更新代理应.
.JBuilder 8新特性简介.
.增强的Windows窗体为.Net程序丰富.
.(10)CDC API.
.利用Java套接字实现网络编程之基.
.commons-fileupload和struts公用.
.开发工具——BREW是什么?.
.Java技巧:用Java保存位图文件.
.彻底明白Java的IO系统.
.加法运算符 (+).
.如何设置application 变量.
.设计模式在EJB中的应用(1).
.getDate 方法.

Java程序的脏数据问题处理

发表日期:2008-1-5



  脏数据(Out-of-date data),指过时的数据。
  
  假如在您的Java程序中存在脏数据,将或多或少地给软件系统带来一些问题,如:无法实时地应用已经发生改变的配置,软件系统出现一些莫名其妙的、难以重现的、后果严重的错误等等。尽量避免脏数据的存在是非常有价值的。本文希望能在这方面给同行们一点帮助。
  
  Fragment 1. 缓存技术的脏数据问题
  
  /**
  * A report printer is used to print a report.
  *
  * @version 1.0 9/9/2003
  * @author Bill
  */
  public class ReportPrinter {
  /**
  * ConstrUCts a <code>ReportPrinter</code> instance.
  */
  public ReportPrinter() {
  // do something...
  }
  
  /**
  * Prints a printable.
  *
  * @param printable the specified printable object
  */
  public void print(Printable printable) {
  Graphics g = getGraphics();
  g.setFont(getReportFont(printable.getFont());
  
  printable.print(g);
  }
  
  /**
  * Returns the corresponding report font of a java font.
  *
  * @param javaFont the specified java font
  * @return the corresponding report font
  */
  private Font getReportFont(font javaFont) {
  Font reportFont = fontMap.get(javaFont);
  
  if(reportFont == null) {
  reportFont = loadFont(javaFont);
  fontMap.put(javaFont, reportFont);
  }
  
  return reportFont;
  }
  
  /**
  * Loads the corresponding report font of a java font.
  *
  * @param javaFont the specified java font
  * @param the corresponding report font
  */
  protected static Font loadFont(Font javaFont) {
  Font reportFont = null;
  
  // do something...
  
  return reportFont;
  }
  
  /**
  * The font map(java font->report font).
  */
  private static HashMap fontMap = new HashMap();
  }
  
  Fragment 1中,由于装载一个java font所对应的report font开销较大,使用了缓存技术来避免这种开销。这是一种常见的提高性能的方式,而且在一般情况下运行良好。但是Fragment 1的设计与实现可能是不完备的,因为极有可能一个java font所对应的report font在系统启动之后发生变化,在这种变化发生之后,只有重启软件系统才能装载之,这经常是最终用户的抱怨之一。更可怕的是,类似的这种脏数据的存在还可能带来其它严重的、无法想象的后果。
  
  如何避免使用缓存技术所带来的脏数据问题呢?
  
  在设计、实现和测试时,应该清楚定义缓存数据的更新:
  i. 不考虑缓存数据的更新,重启软件系统是一种必要的方式;
  ii. 不考虑缓存数据的更新,缓存数据不可能成为脏数据(但在软件系统中,往往“不可能”会在一次又一次的重构之后变为“可能”);
  iii. 考虑缓存数据的更新,当源数据变化时,实时更新缓存数据。
  
  Fragment 2. Singleton模式的脏数据问题
  
  /**
  * A storage usage handler is used to query the storage usage of users.
  *
  * @version 1.0 9/9/2003
  * @author Bill
  */
  public class StorageUsageHandler {
  /**
  * Returns a <code>StorageUsageHandler</code> instance.
  *
  * @return the single <code>StorageUsageHandler</code> instance
  */
  public static StorageUsageHandler getStorageUsageHandler() {
  if(handler == null) {
  handler = new StorageUsageHandler();
  }
  
  return handler;
  }
  
  /**
  * Constructs a <code>StorageUsageHandler</code> instance.
  */
  private StorageUsageHandler() {
  users = Context.getAllUsers();
  }
  
  /**
  * Returns the storage sizes of all the users.
  *
  * @return the storage sizes
  */
  public long[] getSizes() {
  long sizes[] = new long[users.size()];
  
  for(int i = 0; i < users.size(); i++) {
  sizes[i] = getOneSize(users.get(i));
  }
  }
  
  /**
  * Returns the storage size of a user.
  *
  * @param user the specified user
  * @return the storage size
  */
  protected long getSize(User user) {
  // do something...
  
  return 0;
  }
  
  /**
  * The <code>StorageUsageHandler</code> singleton.
  */
  private static StorageUsageHandler handler;
  
  /**
  * The users.
  */
  private List users;
  }
  
  您看出了问题所在吗?
  
  Fragment 2中,由于没有必要次次实例化StorageUsageHandler而带来不必要的开销,采用了Singleton模式以保证StorageUsageHandler只被实例化一次。
  
  在实例化SotrageUsageHandler时,StorageUsageHandler的类成员users将被赋值。由于不存在任何对users重新赋值的方法,一直驻留在软件系统中的users将不会发生任何变化。在软件系统启动之后,增加、删除或修改用户的操作经常会发生,而一旦发生这类操作,users就成为了脏数据,Fragment 2将无法正常工作。
  
  如何避免使用Singleton模式所带来的脏数据问题呢?
  
  对于Singleton类的类成员:
  i. 对于与Singleton类外部无依靠关系的类成员,不存在这种问题;
  ii. 对于依靠于Singleton类外部的类成员,且该类成员不存在更新机制,最好是将其去掉,需要时从Singleton类外部直接获取;假如这种办法不可行,应提供机制以确保在使用该类成员之前,该类成员已经被更新过。
  
  Fragment 3. 类使用的脏数据问题
  
  /**
  * A storage usage handler is used to query the storage usage of users.
  *
  * @version 1.0 9/9/2003
  * @author Bill
  */
  public class StorageUsageHandler implements AdminHandler {
  /**
  * Constructs a <code>StorageUsageHandler</code> instance.
  */
  private StorageUsageHandler() {
  users = Context.getAllUsers();
  }
  
  /**
  * Returns the storage sizes of all users.
  *
  * @return the storage sizes
  */
  public long[] getSizes() {
  long sizes[] = new long[users.size()];
  
  for(int i = 0; i < users.size(); i++) {
  sizes[i] = getOneSize(users.get(i));
  }
  }
  
  /**
  * Returns the storage size of a user.
  *
  * @param user the specified user
  * @return the storage size
  */
  protected long getSize(User user) {
  // do something...
  
  return 0;
  }
  
  /**
  * Displays the storage usage of users.
  *
  * @param req the http servlet request
  * @param res the http servlet response
  *
  * @throws IOException
  * @throws ServletException
  */
  public void process(HttpServletRequest req, HttpServletResponse res)
  throws IOException, ServletException {
  
  res.setContentType("text/Html");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Pragma","no-cache");
  res.setDateHeader("EXPires", 0);
  
  PrintWriter writer = new PrintWriter(res.getOutputStream());
  long sizes[] = getsizes();
  writer.println("<html><title>Storage Usage</title><body>");
  writer.println("<table width='100%'>");
  
  for(int i = 0; i < sizes.length; i++) {
  writer.print("<tr><td align='center' nowrap>");
  writer.print(users.get(i) + ": " + sizes[i]);
  writer.println("</td></tr>");
  }
  
  writer.println("</body></html>");
  writer.flush();
  writer.close();
  }
  
  /**
  * The users.
  */
  private List users;
  }
  
  /**
  * An admin servlet as a http servlet to process the admin http servlet
  * request and response.
  *
  * @version 1.0 9/9/2003
  * @author Bill
  */
  public class AdminServlet extends HttpServlet {
  /**
  * Initiates the configuration.
  *
  * @param config the servlet config
  *
  * @throws ServletException
  */
  private void initConfig(ServletConfig config) throws ServletException {
  // do somet
上一篇:详细讲解怎样在Java中运行其它应用程序 人气:505
下一篇:StarSuite 6.0和SDK安装以及配置指南之一 人气:728
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐