Java中的RAII

资源获取即初始化( RAII )是Bjarne Stroustrup用C ++引入的一种用于异常安全资源管理的设计思想。 感谢垃圾回收,Java 没有此功能,但是我们可以使用try-with-resources实现类似的功能。

约翰·哈德斯(John Huddles)在萨赫姆农场(1998)

RAII解决的问题很明显; 看一下这段代码(我确定您知道Semaphore是什么以及它在Java中的工作方式):

class Foo {private Semaphore sem = new Semaphore(5);void print(int x) throws Exception {this.sem.acquire();if (x > 1000) {throw new Exception("Too large!");}System.out.printf("x = %d", x);this.sem.release();}
}

该代码相当原始,没有任何用处,但您很可能会明白:如果从多个并行线程调用方法print() ,则只允许其中五个并行打印。 有时,如果x大于1000 ,将不允许其中的一些打印,并且将引发异常。

该代码的问题是资源泄漏 。 x大于1000每个print()调用都会从信号量中获取一个许可,并且不会返回它。 在五个异常调用中,信号量将为空,所有其他线程将不打印任何内容。

解决办法是什么? 这里是:

class Foo {private Semaphore sem = new Semaphore(5);void print(int x) throws Exception {this.sem.acquire();if (x > 1000) {this.sem.release();throw new Exception("Too large!");}System.out.printf("x = %d", x);this.sem.release();}
}

抛出异常之前,我们必须释放许可证。

但是,还有另一个问题出现:代码重复。 我们在两个地方发放许可证。 如果我们添加更多的throw指令,我们还必须添加更多的sem.release()调用。

在C ++中引入了一个非常优雅的解决方案,称为RAII。 这是在Java中的外观:

class Permit {private Semaphore sem;Permit(Semaphore s) {this.sem = s;this.sem.acquire();}@Overridepublic void finalize() {this.sem.release();}
}
class Foo {private Semaphore sem = new Semaphore(5);void print(int x) throws Exception {new Permit(this.sem);if (x > 1000) {throw new Exception("Too large!");}System.out.printf("x = %d", x);}
}

看看方法Foo.print()的代码多么漂亮。 我们只创建了Permit类的实例,它立即在信号量上获得了一个新的许可。 然后我们通过异常或正常方式退出方法print() ,然后方法Permit.finalize()释放许可。

优雅,不是吗? 是的,是的,但是在Java中不起作用。

它不起作用,因为与C ++不同,Java在可见性关闭时不会破坏对象。 当我们退出方法print()时, Permit类的对象不会被破坏。 它最终将被销毁,但我们不知道确切的时间。 获得信号灯中的所有许可之后,很可能将其破坏,并且我们将被阻止。

Java中也有一个解决方案。 它不像C ++那样优雅,但确实有效。 这里是:

class Permit implements Closeable {private Semaphore sem;Permit(Semaphore s) {this.sem = s;}@Overridepublic void close() {this.sem.release();}public Permit acquire() {this.sem.acquire();return this;}
}
class Foo {private Semaphore sem = new Semaphore(5);void print(int x) throws Exception {try (Permit p = new Permit(this.sem).acquire()) {if (x > 1000) {throw new Exception("Too large!");}System.out.printf("x = %d", x);}}
}

请注意try块和Permit类现在实现的Closeable接口。 try块退出时,对象p将被“关闭”。 它可以在结尾处退出,也可以通过returnthrow语句退出。 无论哪种情况,都会调用Permit.close() :这就是try-with-resources在Java中的工作方式。

我介绍的方法acquire()和感动sem.acquire()出的Permit构造,因为我相信这构造函数必须是免费的代码。

总而言之,RAII是一个完美的设计 图案 处理可能泄漏的资源时的方法。 即使Java没有开箱即用,我们也可以通过try-with-resources和Closeable实现它。

翻译自: https://www.javacodegeeks.com/2017/08/raii-in-java.html

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

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

相关文章

java去掉字符串中前后空格函数_Java去除字符串中的空格

1. String.trim()trim()是去掉首尾空格2.str.replace(" ", ""); 去掉所有空格,包括首尾、中间String str " hell o ";String str2 str.replaceAll(" ", "");System.out.println(str2);3.或者replaceAll("…

python3开发工具推荐_python开发工具有哪些?我推荐这5款python开发工具!

python开发工具有很多,目前我们用的比较多的是pycharm,除了pycharm还有文本编辑器像微软的vscode,sublime text都有非常好的插件,今天,我就把Python程序员使用频率比较高的5款开发工具推荐给大家,希望对大家…

java显示数据库 控件_WebLogic运用DB的Java控件访问数据库(1)

一、方法WebLogic页面与数据通信时,一般采用Java控件直接访问数据连接池,数据的直接操作都定义在Java控件中,页面流做为数据的逻辑处理单元,普通页面做为显示层。可以看出WebLogic这个方法是典型的三层结构,数据层(Jav…

python的实验报告怎么写_学号:20191221,《python实验设计》实验报告三

学号 2019-2020-2 《Python程序设计》实验三讲述课程:《Python程序设计》班级: 1912姓名: 何应霆学号:20191221实验西席:王志强实验日期:2020年5月16日必修/选修: 公选课1.实验内容建立服务端和…

eclipse juno_Eclipse Juno上带有GlassFish的JavaEE 7

eclipse junoJava EE 7很热。 前四个JSR最近通过了最终批准选票,与此同时GlassFish 4达到了升级版83。 如果您关注我的博客,那么您将了解NetBeans的大部分工作。 但是我确实认识到,那里还有其他IDE用户,他们也有权试用最新和最出色…

java 生成校验验证码_java 验证码生成与校验

java绘图相关类验证码工具类package dt2008.util;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.awt.*;import java.awt.image.BufferedImage;import java.io.IOException;import ja…

红黑树中nil结点_什么是红黑树?程序员面试必问!

点击上方java小组,选择“置顶公众号”优质文章,第一时间送达当在10亿数据中只需要进行10几次比较就能查找到目标时,不禁感叹编程之魅力!人类之伟大呀! —— 学红黑树有感。终于,在学习了几天的红黑树相关的…

杰克逊JSON解析错误-UnrecognizedPropertyException:无法识别的字段,未标记为可忽略[已解决]...

在解析从我们的一个RESTful Web服务接收到的JSON字符串时,我收到此错误“线程“ main”中的异常com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“人”(类Hello $ Person),不是标记…

mysql2008数据库配置_SQL Server 2008 R2 超详细安装图文教程

这篇文章主要介绍了SQL Server 2008 R2 超详细安装图文教程,需要的朋友可以参考下一、下载SQL Server 2008 R2安装文件二、将安装文件刻录成光盘或者用虚拟光驱加载,或者直接解压,打开安装文件,出现下面的界面安装SQL Server 2008 R2需要.NET…

hdfs读写流程_深度探索Hadoop分布式文件系统(HDFS)数据读取流程

一、开篇Hadoop分布式文件系统(HDFS)是Hadoop大数据生态最底层的数据存储设施。因其具备了海量数据分布式存储能力,针对不同批处理业务的大吞吐数据计算承载力,使其综合复杂度要远远高于其他数据存储系统。因此对Hadoop分布式文件系统(HDFS)的深入研究&a…

python可视化分析网易云音乐评论_Python数据可视化:网易云音乐歌单

网易云音乐2018年度听歌报告—遇见你,真好。相信有不少人在上周,应该已经看过自己网易云音乐的年度报告了。小F也是去凑凑热闹,瞅了一波自己的年度听歌报告。那么你在云村又听了多少首歌,听到最多的歌词又是什么呢?2018年你的年度…

mysql隔离级别验证_MySQL事务隔离级别以及验证

查询初始数据开启A事务  并做更新操作再另一端 B开始另一个事务查询 事务级别设置为读未提查询到事务未提交的数据 a的count修改为3 但是没有提交2 第二个级别 读已提交 避免脏读问题 但是有不可重复读问题回滚数据 修改隔离级别 确保都是 读已提交级别客户端A客户端B验证 脏…

登录样式:log4j 2,上下文,自动清除…全部不附加任何字符串!

日志记录-保持操作的时间跟踪-对于任何关键任务系统,无论大小,都至关重要。 我们的Project-X框架也是如此 ,这就是为什么我们希望从一开始就正确地做到这一点。 基于我们在传奇的UltraESB上的登录经验, 上下文日志记录&#xff0…

python37安装失败_Linux 安装Python37

1、下载python3.7.0https://www.python.org/downloads/release/python-370/2、创建Linux的python37目录mkdir /usr/local/python373、解压python3.7.0源码tar zxvf python3.7.0.tar.zg4、配置编译参数./configure --prefix/usr/local/python375、make6、make install注意&#…

python string模块template_Python标准库笔记(1) — string模块

String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作。1. 常用方法常用方法描述str.capitalize()把字符串的首字母大写str.center(width)将原字符串用空格填充成一个长度为width的字符串,原字符串内容居中str.count…

注意力机制可视化_目标跟踪中的(STAM)时空注意力机制

目标跟踪分为单目标跟踪和多目标跟踪,单目标跟踪较为简单,这里我们只讨论多目标跟踪。多目标跟踪的遮挡问题多目标跟踪时特别容易发生目标间的相互遮挡,从而导致严重的预测偏移问题,如下图所示:红色框的行人在和蓝色框…

byteman_使用Byteman和JUnit进行故障注入

byteman我们的应用程序独立存在的时间已经很久了。 如今,应用程序是一种非常复杂的野兽,它们使用无数的API和协议相互通信,将数据存储在传统或NoSQL数据库中,通过网络发送消息和事件……例如,您多久考虑一次例如数据库…

java动态扩展_java栈内存动态扩展要怎么理解?要如何实现?

小伙伴们知道如何在java栈中内存动态扩展吗?这是虚拟机中的一个概念,下面让我们一起来看看该如何实现吧。一、内存概念在java中,我们一般会简单把java内存区域划为两种:堆内存与栈内存。其实这种划分是比较粗粒度的。其中栈内存就是指的是虚…

python 爬虫热搜_Python网络爬虫之爬取微博热搜

微博热搜的爬取较为简单,我只是用了lxml和requests两个库1.分析网页的源代码:右键--查看网页源代码.从网页代码中可以获取到信息(1)热搜的名字都在的子节点里(2)热搜的排名都在的里(注意置顶微博是没有排名的!)(3)热搜的访问量都在的子节点里…

优盘复制进来为空_为何电脑上的文件夹一复制到U盘里就变成空文件夹了?

(格式化后的卡在恢复前千万不要往里面存东西,因为这样会覆盖你想恢复的内容,如果你不小心存东西了也不要放弃,只不过恢复的机率会变小),下面开始:::在百度里输入Easy recover 软件找到后下载安装到电脑上,然后将内存卡与电脑连接,打开Easy recover 软件,首次打开时软件会分析系…