怎么简单的锁定文件夹_简单性与鲁棒性–在锁定文件处理中展示

怎么简单的锁定文件夹

今天,我们将讨论使事情保持简单,愚蠢(KISS)和鲁棒性的设计价值之间,设计不足和过度设计之间的冲突。

我们正在编写一个批处理Java应用程序,需要确保在服务器上一次最多运行一个实例。 团队成员有一个很好的想法,那就是使用锁定文件,这确实有效并且对我们有很大帮助。 但是,最初的实现不是很健壮,由于对该死的应用程序拒绝运行和查找锁定文件进行故障排除,这使我们花费了宝贵的时间和昂贵的上下文切换。

正如Comoyo的ØyvindBakksjø最近解释的那样,软件工程师与纯粹的编码器的不同之处在于,不仅要思考和关心通过代码的快乐路径,而且还要考虑不快乐的情况。 优秀的工程师会考虑可能出现的问题,并尝试适当地处理它们,以便依赖于它们和其用户的代码可以更轻松地处理有问题的情况。 健壮性包括及早发现错误,以良好的方式处理错误以及提供有用和有用的错误消息。 另一方面,简单性[TBD:Hickey]是系统的关键特征。 花太多时间来制作防弹代码总是很容易,而不是将精力集中在对业务更有价值的地方。

过于简单的实现

最初的实现非常简单:

public class SimpleSingletonBatchJob {private static boolean getLock() {File file = new File(LOCK_DIRECTORY+File.separatorChar+Configuration.getGroupPrefix());try {return file.createNewFile();} catch (IOException e) {return false;}}private static void releaseLock() {File file = new File(LOCK_DIRECTORY+File.separatorChar+Configuration.getGroupPrefix());file.delete();}public static void exit(int nr) {releaseLock();System.exit(nr);}public static void main(String[] args) throws IOException {...if (! getLock()) { // #1 try to create lockSystem.out.println("Already running");return;}... // do the job (may throw exceptions)releaseLock(); // #2 release lock when done}
}

主要问题是,如果该应用程序失败或被终止,它将留下锁定文件,而下次它将拒绝并以无用的错误消息开头。 您将需要了解/阅读代码以了解如何解决问题。

有人认为,这样的失败和故意的失败只会很少发生,以致于使代码更健壮的努力是没有道理的。 但是,我们需要投入很少的精力来使代码更加友好和健壮,f.ex。 通过在错误消息中包括锁定文件路径并解释为什么可能存在锁定文件路径以及如何解决该问题(例如“如果应用未运行,则锁定是失败运行的残余,可能会被删除”)。 确保在失败时删除文件是一些琐碎的代码行,可以节省一些混乱和时间。 另外,值得一提的是使其更强大,从而不需要太多的人工干预–对您的操作人员很友好。 (我希望是你。)

更强大的实施

这是改进的版本,具有有用的错误消息,并在失败时删除锁:

public class RobustSingletonBatchJob {// Note: We could use File.deleteOnExit() but the docs says it is not 100% reliable and recommends to// use java.nio.channels.FileLock; however this code works well enough for usstatic synchronized boolean getLock() {File file = new File(LOCK_DIRECTORY, StaticConfiguration.getGroupPrefix());try {// Will try to create path to lockfile if it does not exist.file.getParentFile().mkdirs(); // #1 Create the lock dir if it doesn't existif (file.createNewFile()) {return true;} else {log.info("Lock file " + file.getAbsolutePath() + " already exists."); // #2 Helpful error msg w/ pathreturn false;}} catch (IOException e) {throw new RuntimeException("Failed to create lock file " + file.getAbsolutePath()+ " due to " + e + ". Fix the problem and retry.", e); // #3 Helpful error message with context (file path)}}private synchronized static void releaseLock() {File file = new File(LOCK_DIRECTORY, StaticConfiguration.getGroupPrefix());file.delete();}public static void main(String[] args) throws Exception {boolean releaseLockUponCompletion = true;try {...if (! getLock() {releaseLockUponCompletion = false;log.error("Lock file is present, exiting."); // Lock path already loggedthrow new RuntimeException("Lock file is present"); // throwing is nicer than System.exit/return}... // do the job (may throw exceptions)} finally {if (releaseLockUponCompletion) {releaseLock(); // #4 Always release the lock, even upon exceptions}}
}

改进之处:

  1. 如果不存在锁,则创建一个存储锁的目录(该锁不存在,并导致令人困惑的“已运行”错误消息)已经使我们感到痛苦
  2. 有用的错误消息“锁定文件<文件的绝对路径>已存在。” =>易于复制和粘贴int rm
  3. 有用的错误消息,其中包含文件路径和错误信息,当我们无法创建锁时(空间不足,目录权限不足等)。
  4. 将整个主程序包装起来进行尝试–最后,确保始终删除锁定文件

代码仍然不是完美的-如果您终止了该应用程序,则锁定文件仍将留下。 有多种方法可以解决该问题(例如,将应用程序的pid包含在文件中,在启动时不仅检查其是否存在,而且还应检查pid确实存在/是否为该应用程序),但是在处理时间方面和增加成本方面复杂性的确高于收益。

结论

KISS和鲁棒性都是重要目标,并且经常会发生冲突。 使您的代码变得比所需的更健壮会使其变得过于复杂,并浪费时间,并且机会成本(丢失)。 由于故障排除,使代码过于简单会花费您或它的用户大量时间。 要实现正确的平衡,需要经验并不断地寻求平衡。 如果您的团队无法达成共识,最好从一个简单的代码开始,并根据其实际的健壮性需求收集硬数据,而不是事先对其进行过度设计。 不要像我一样成为完美主义者,但也要对您的用户和开发者同好。 如果您可以毫不费力地使您的应用程序更强大,那就去做吧。 如果需要更多工作,请去收集数据以证明(或不需要)该工作。

参考: 简单性与鲁棒性–在Wonders of Code博客上由我们的JCG合作伙伴 Jakub Holy 演示了锁定文件处理 。

翻译自: https://www.javacodegeeks.com/2013/09/simplicity-vs-robustness-demonstrated-on-lock-file-handling.html

怎么简单的锁定文件夹

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php strlen 线程安全,浅析PHP中strlen和mb_strlen的区别

在PHP中&#xff0c;strlen与mb_strlen是求字符串长度的函数&#xff0c;但是对于一些初学者来说&#xff0c;如果不看手册&#xff0c;也许不太清楚其中的区别。下面通过例子&#xff0c;讲解这两者之间的区别。先看例子&#xff1a;//测试时文件的编码方式要是UTF8$str中文a字…

单片机float数发给上位机_上位机倒计时器

1. 设置窗口在VS2019新建一个Windows窗体应用(.NET Framework)项目&#xff0c;新建之后出现一个可视化页面(From1.cs[设计])设置窗口。在左侧的工具箱里面拉拽控件到操作面板上&#xff0c;按照自己的喜好摆放位置和调大小。这里要注意的是用到的分别是什么控件&#xff1a;文…

JDK语言功能预览:切换表达式

JEP 12 [“预览语言和VM功能”]在其主页上描述如下&#xff1a; 预览语言或VM功能是Java SE平台的一项新功能&#xff0c;该功能已完全指定&#xff0c;完全实现但不是永久性的。 JDK功能发布中提供了该功能&#xff0c;以根据实际使用情况激发开发人员反馈。 这可能会导致它在…

python快速示例_Python编程入门-基本示例,快速,上,手,基础

环境配置安装Python&#xff0c;目前最新的是3.9(不支持Windows7)&#xff0c;我装的3.7https://www.python.org/downloads/安装向导里勾选自动添加路径&#xff0c;装完就可以用&#xff0c;Windows10/7搜索框输入IDLE&#xff0c;进入交互式环境窗口&#xff0c;输入语句后&a…

php 距离排序,php 附近由近到远排序查询

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼//获取经纬度 默认值为0.5千米function returnSquarePoint($lng, $lat, $distance 0.5){define(EARTH_RADIUS, 6371); //地球半径&#xff0c;平均半径为6371km$dlng 2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2ra…

土地利用覆被变化的概念_欠压实概念极其荒谬

●李传亮地表疏松的沉积物&#xff0c;孔隙度极高&#xff0c;有时可高达80%以上&#xff0c;但随着埋藏深度的加大&#xff0c;在上覆压力的作用下&#xff0c;其排列方式不断由松散排列趋于致密排列&#xff0c;同时伴随有孔隙度的大幅度减小&#xff0c;此即岩石的压实阶段&…

java方法带参数返回值_Java方法中的参数太多,第6部分:方法返回

java方法带参数返回值在当前的系列文章中&#xff0c;我正在致力于减少调用Java方法和构造函数所需的参数数量&#xff0c;到目前为止&#xff0c;我一直专注于直接影响参数本身的方法&#xff08; 自定义类型 &#xff0c; 参数对象 &#xff0c; 构建器模式 &#xff0c; 方法…

java足球游戏毕业设计,java毕业设计_springboot框架的校园足球管理平台

今天介绍一个java毕设题目, 题目内容为springboot框架的校园足球管理平台, 是一个采用b/s结构的javaweb项目, 采用java语言编写开发工具eclipse, 项目框架jspspringbootmybatis, 校园足球管理平台的信息存储于mysql中, 并基于mybatis进行了orm封装, 该校园足球管理平台系统通过…

python 爬取贝壳网小区名称_用Python爬取贝壳网新房和二手房数据

[Python] 纯文本查看 复制代码import randomimport requestsfrom bs4 import BeautifulSoupimport reimport mathfrom lxml import etreeUSER_AGENTS ["Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)&q…

Java 11功能– Java飞行记录器

在本文中&#xff0c;我们将看到如何利用Java Flight Recorder功能作为Java 11的一部分。之前&#xff0c;它是商业功能之一。 但是&#xff0c;对于带有JEP 328的 Java 11&#xff0c;它是开源的。 Java Flight Recorder将OS和JVM事件记录到一个文件中&#xff0c;可以使用Jav…

MATLAB slider中的数值,在微信小程序中如何使用slider设置数据值

这篇文章主要介绍了微信小程序使用slider设置数据值及switch开关组件功能,结合实例形式分析了slider组件及switch组件的功能与使用方法,并附带源码供读者下载参考,需要的朋友可以参考下本文实例讲述了微信小程序使用slider设置数据值及switch开关组件功能。分享给大家供大家参考…

qstandarditemmodel 重写data函数后无法实现拖拽_实现类似百度网盘上传的功能

今天写到了上传文件部分&#xff0c;记录一下。前端使用了dropzone.js(用于实现文件上传的JS库)&#xff0c;并对此文件进行了细微修改。说一下思路吧&#xff1a;首先界面长这样&#xff1a;点击上传文件&#xff0c;需要弹出一个对话框&#xff0c;对话框中有支持拖拽文件的文…

逻辑斯蒂回归_逻辑斯蒂回归详细解析 | 统计学习方法学习笔记 | 数据分析 | 机器学习...

本文包括&#xff1a;重要概念逻辑斯蒂回归和线性回归二项逻辑斯谛回归模型逻辑斯蒂回顾与几率模型参数估计多项逻辑斯谛回归其它有关数据分析&#xff0c;机器学习的文章及社群1.重要概念&#xff1a;在正式介绍逻辑斯蒂回归模型之前&#xff0c;需要先对一些基本概念有所了解…

mysql 数据传输 定时,MySQL数据库定时备份的实现方法

1. 创建shell脚本2. 给shell脚本添加执行权限3. 给脚本添加定时任务crontab文件的说明&#xff1a;用户创建的crontab文件中&#xff0c;每一行都代表一项定时任务&#xff0c;每行的每个字段代表一项设置&#xff0c;它的格式每行共分为六个字段&#xff0c;前五段是时间设定字…

python 生意_本周互联网关注(2015515):劳动人民的生意经、python好还是go好

我很喜欢写这种类型的文章&#xff0c;写的也轻松&#xff0c;大家看的也多。性价比高。那么现在继续。一、所谓光辉岁月&#xff0c;不是波澜壮阔的时候&#xff0c;而是无人问津时&#xff0c;你对梦想的坚持。| 陈欧很多人刚开始创业时激情无比高涨&#xff0c;干着干着开始…

mysql空洞数据,Mysql 表空间和 数据页空洞

一、表空间1、表空间&#xff1a; innodb 引擎存储的最高层&#xff1b; 存放所有的数据2、独立表空间&#xff1a;Mysql 版本5.6 后默认开启的单表单空间(1)Innodb 默认存储引擎页的大小为 16K &#xff1b;默认表空间 大小为96k(2)独立表空间 开启方式 innodb_file_per_table…

junit 5测试异常处理_在JUnit中处理异常的3种方式。 选择哪一个?

junit 5测试异常处理在JUnit中&#xff0c;有3种流行的方式来处理测试代码中的异常&#xff1a; 试捕习语 使用JUnit规则 带注解 我们应该使用哪一个&#xff1f;何时使用&#xff1f; 试捕习语 这个习语是最受欢迎的习语之一&#xff0c;因为它已在JUnit 3中使用。 Test…

python网站数据写入mysql_python网络爬虫抓取动态网页并将数据存入数据库MySQL

简述以下的代码是使用python实现的网络爬虫&#xff0c;抓取动态网页 http://hb.qq.com/baoliao/ 。此网页中的最新、精华下面的内容是由JavaScript动态生成的。审查网页元素与网页源码是不同。以上是网页源码以上是审查网页元素所以此处不能简单的使用正则表达式来获取内容。以…

交通流预测 | Matlab基于KNN-BiLSTM的交通流预测(对比SVR、LSTM、GRU、KNN-LSTM)

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 交通流预测 | Matlab基于KNN-BiLSTM的交通流预测&#xff08;对比SVR、LSTM、GRU、KNN-LSTM&#xff09; 程序设计 完整程序和数据获取方式&#xff1a;私信博主回复Matlab基于KNN-BiLSTM的交通流预测&#xff08;对…

JMetro“ Metro”选项卡,Java的TreeView和ContextMenu(JavaFX)

我刚刚发布了JMetro的新更新&#xff0c;将版本升级到3.3.0。 在此更新中&#xff0c;您将找到&#xff1a; 新的TreeView Fluent设计系统&#xff08;Metro&#xff09;启发风格&#xff1b; 新的Tabs和TabPane FDS启发风格&#xff1b; 新的上下文菜单采用深色FDS启发的样…