千家信息网

Java程序的脏数据问题实例分析

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,本篇内容主要讲解"Java程序的脏数据问题实例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java程序的脏数据问题实例分析"吧!脏数据(Out-of
千家信息网最后更新 2025年01月19日Java程序的脏数据问题实例分析

本篇内容主要讲解"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("");
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程序的脏数据问题实例分析"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

数据 问题 成员 实例 更新 缓存 系统 软件 软件系统 模式 程序 机制 变化 实例分析 分析 办法 开销 技术 方式 用户 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 饥荒联机版加载服务器卡顿 最新一次人口普查数据库 03服务器卡在应用安全策略 森维网络安全知识 网络安全如何分级管理 网络安全工段领导小组 南京编程软件开发机构 浙江长兴有哪些软件开发公司 成都义幻网络技术有限公司 杭州蓝樱网络技术有限公司 海曙软件开发 计算机网络安全第一章总结 学软件开发出去做什么岗位 华为V5服务器硬盘数据清除 图片以二进制存入数据库 宝山区信息化软件开发有哪些 盛行时代网络安全吗 软件开发需要具备哪些 贯彻落实网络安全责任制实施细则 数据库连接客户端 义乌工业软件开发流程八个步骤 软件开发的前端是 liunx下执行数据库脚本 ssms中数据库文件在哪里 数据库日期小于系统时间怎么写 广州市网络安全会议 信汇宝网络技术有限公司 英国留学网络安全吗 食品数据库 营养成分 中专有计算机网络技术吗
0