中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java程序的臟數據問題實例分析

發布時間:2022-01-10 15:50:24 來源:億速云 閱讀:121 作者:iii 欄目:編程語言

本篇內容主要講解“Java程序的臟數據問題實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java程序的臟數據問題實例分析”吧!

  臟數據(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 ReportPrinter 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 StorageUsageHandler instance.
  *
  * @return the single StorageUsageHandler instance
  */
  public static StorageUsageHandler getStorageUsageHandler() {
  if(handler == null) {
  handler = new StorageUsageHandler();
  }

  return handler;
  }

  /**
  * Constructs a StorageUsageHandler 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 StorageUsageHandler 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 StorageUsageHandler 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("Storage Usage");
  writer.println("

");

  for(int i = 0; i < sizes.length; i++) {
  writer.print("

");
  }

");
  writer.print(users.get(i) + ": " + sizes[i]);
  writer.println("

  writer.println("");
  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 something...

  handlerMap.put("__storage_Usage__", new StorageUsageHandler());
  }

  /**
  * Processes the http servlet request and response.
  *
  * @throws IOException
  * @throws ServletException
  */
  public void service(HttpServletRequest req, HttpServletResponse res)
  throws IOException, ServletException {

  AdminHandler handler = handlerMap.get(req.getParameter("handler"));

  if(handler == null) {
  // do something...

  return;
  }

  handler.process(req, res);
  }

  /**
  * The admin handler map(handler name->handler).
  */
  private HashMap handlerMap = new HashMap();
  }

  您一定看出了問題所在吧!
  Fragment 3中,由于StorageUsageHandler并不遵循Singleton模式,盡管StorageUsageHandler的類成員users只能在實例化StorageUsageHandler時被賦值,但是在單線程模式下,只要保證每次所使用的StorageUsageHandler實例是新實例化的,基本上還是沒有問題的。
  問題在于,在初始化AdminServlet的過程中,StorageUsageHandler被實例化并存儲起來。此后,除非servlet container重新裝載AdminServlet,否則將無法重新實例化StorageUsageHandler,也將無法更新StorageUsageHandler的類成員users。這樣,在發生了增加、刪除或修改用戶的操作之后,users將成為臟數據。
  如何避免類使用所帶來的臟數據問題呢?
  i. 對于與類外部無依賴關系的類成員,不存在這種問題;
  ii. 對于依賴于類外部的類成員,且該類成員不存在更新機制。最好是將其去掉,需要時從類外部直接獲取;如果這種辦法不可行,應提供機制以確保在使用該類成員之前,該類成員已經被更新過;如果這種辦法還不可行,請清晰地說明類的使用方式,以防止不當的類使用發生。

到此,相信大家對“Java程序的臟數據問題實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

灵寿县| 桃江县| 石台县| 丁青县| 成安县| 南涧| 裕民县| 甘德县| 工布江达县| 保靖县| 焦作市| 哈尔滨市| 咸丰县| 和硕县| 雷州市| 兰西县| 宁远县| 永靖县| 东台市| 岑巩县| 怀宁县| 平顶山市| 廊坊市| 通化县| 泗洪县| 莱西市| 宜春市| 驻马店市| 郯城县| 铁力市| 广平县| 罗甸县| 习水县| 马鞍山市| 同江市| 嘉黎县| 浏阳市| 长治市| 红原县| 兴城市| 安宁市|