• 科普文:一文搞懂jvm实战(三)AutoCloseable回收jvm资源


    概叙

    科普文:一文搞懂jvm实战(一)Runtime实时监控jvm-CSDN博客

    科普文:一文搞懂jvm实战(二)Cleaner回收jvm资源-CSDN博客

            在前面Cleaner回收jvm资源中,就可以看到 AutoCloseable接口,实现close()方法完成资源回收。

            AutoCloseable 是从 jdk7 开始存在的接口,位于 java.lang 包中,用于自动执行资源关闭操作。AutoCloseable 接口定义了一个名为 close() 的方法,用于关闭资源。通常在实现 AutoCloseable 接口的类中重写 close() 方法来实现自定义关闭资源的逻辑,例如关闭文件、释放网络连接等。

            AutoCloseable 接口是为了配合 Java 7 引入的 try-with-resources(try-catch-finally) 语句而设计的。使用 try-with-resources 语句可以自动关闭实现了 AutoCloseable 接口的资源,无需显式调用 close() 方法,确保资源在使用完毕后被正确关闭,提高代码的可靠性和安全性。

    AutoCloseable接口

    自动关闭,释放资源机制

            在实际的项目开发过程中,一般都有可能连接到一些资源,比如:文件资源、网络资源、数据库资源,在实际项目之中进行资源访问的社会一般有如下几个操作步骤:

    不使用AutoCLoseable:

    手动定义关闭函数

            按照正常的结构设计来讲,当前的程序已经可以满足整个设计上的开发要求,因为有正常的连接同时又可以进行服务器断开访问

    1. import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
    2. //接口
    3. interface IMessage{
    4. public void send(String msg);//发送消息的核心功能
    5. }
    6. //实现接口的类
    7. class NetMassage implements IMessage{
    8. //无参构造
    9. //当前的设计为:只要实例化了此类对象就表示要进行消息的发送。则就需要连接网络服务器
    10. public NetMassage() {
    11. System.out.println("【连接】连接远程服务器,创建消息的服务通道....");
    12. }
    13. @Override
    14. public void send(String msg) {
    15. System.out.println("【发送】"+ msg);//模拟数据的发送
    16. }
    17. //关闭/释放资源
    18. public void close(){
    19. System.out.println("【关闭】网络消息发送完毕,断开服务连接器...");
    20. }
    21. }
    22. public class Application {
    23. public static void main(String[] args) {
    24. //实例化
    25. NetMassage massage = new NetMassage();//创建消息发送类
    26. massage.send("发送消息啦!!");
    27. massage.close();//释放资源
    28. }
    29. }

            运行结果如下:

    1. 【连接】连接远程服务器,创建消息的服务通道....
    2. 【发送】发送消息啦!!
    3. 【关闭】网络消息发送完毕,断开服务连接器...

            虽然以上代码已经可以正常实现网络消息的处理模型,但当前的程序本身又存在以下几个问题:

    • 按照正常的设计开发的结构来讲,此时的程序应该是面向接口的开发,应该在接口里面提供所有的核心业务功能
    • 如果此时通过子类获取IMessage接口对象,会发现无法正常的进行close()方法的调用
    • 既然所有的资源在操作完毕之后都需要关闭,那么就可以有一种自动关闭的机制-----AutoCloseable
    • 注意:JDK1.7以上有AutoCloseable

    使用AutoCloseable:

    必须和异常处理语句一起使用!!!!

    1. import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
    2. //接口 继承AutoCloseable类(实现自动关闭)
    3. // AutoCloseable类要和异常捕获一起使用!!!
    4. interface IMessage extends AutoCloseable{
    5. public void send(String msg);//发送消息的核心功能
    6. }
    7. //实现接口的类
    8. class NetMassage implements IMessage{
    9. //无参构造
    10. //当前的设计为:只要实例化了此类对象就表示要进行消息的发送。则就需要连接网络服务器
    11. public NetMassage() {
    12. System.out.println("【连接】连接远程服务器,创建消息的服务通道....");
    13. }
    14. @Override
    15. public void send(String msg) {
    16. System.out.println("【发送】"+ msg);//模拟数据的发送
    17. }
    18. //关闭/释放资源
    19. public void close(){
    20. System.out.println("【关闭】网络消息发送完毕,断开服务连接器...");
    21. }
    22. }
    23. public class Application {
    24. public static void main(String[] args) {
    25. //AutoCloseable类要和异常处理语句一起使用!!!
    26. try ( NetMassage massage = new NetMassage();){
    27. massage.send("发送消息啦!!");
    28. } catch (Exception e) {
    29. }
    30. //massage.close();//释放资源
    31. }
    32. }

            运行结果如下:

    1. 【连接】连接远程服务器,创建消息的服务通道....
    2. 【发送】发送消息啦!!
    3. 【关闭】网络消息发送完毕,断开服务连接器...

            在运行过程中有异常抛出也可以自动关闭: send函数修改如下

    1. @Override
    2. public void send(String msg) {
    3. if(msg.contains("发送消息")){ //手动抛出异常
    4. throw new RuntimeException("异常抛出!!");
    5. }
    6. System.out.println("【发送】"+ msg);//模拟数据的发送
    7. }

            运行结果如下:

    1. 【连接】连接远程服务器,创建消息的服务通道....
    2. 【关闭】网络消息发送完毕,断开服务连接器...

            通过以上的代码可以发现,必须结合异常处理语句之后才可以使用自动关闭的处理机制,如果在调用的过程之中出现有异常close()方法也是可以正常执行调用的。

    示例1:在 try-catch-finally 中使用 AutoCloseable 来自动关闭资源:

    1. 自定义类实现 AutoCloseable 并重写 close() 方法:
    2. public class StreamExample implements AutoCloseable {
    3. private BufferedReader reader;
    4. public StreamExample(String filePath) throws IOException {
    5. reader = new BufferedReader(new FileReader(filePath));
    6. }
    7. public String readLine() throws IOException {
    8. return reader.readLine();
    9. }
    10. /**
    11. * 重写 close() 方法,自定义关闭资源逻辑
    12. * @throws IOException
    13. */
    14. @Override
    15. public void close() throws IOException {
    16. reader.close();
    17. }
    18. }
    19. try-catch-finally 中的使用:
    20. public class BaseTest {
    21. public static void main(String[] args) {
    22. // 在 try() 中使用自定义对象,在执行完 try 逻辑后会自动调用 close() 方法关闭资源。
    23. // 这样无需在 catch 或 finally 中编写关闭资源的逻辑了。
    24. try (StreamExample example = new StreamExample("file.txt")) {
    25. String line = example.readLine();
    26. while (line != null) {
    27. System.out.println(line);
    28. line = example.readLine();
    29. }
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. }
    33. }
    34. }

    示例2:不一定用来关闭资源,可以扩展为其它使用场景:

    1. 比如在 for 循环语句中,遍历每一个元素时,为每一个元素处理日志设置不同的 traceId,方便日志定位跟踪。
    2. @Slf4j
    3. public class TraceExample implements AutoCloseable {
    4. /**
    5. * 进入循环之前的traceId
    6. */
    7. private String beforeTraceId;
    8. public TraceExample(String beforeTraceId) {
    9. try {
    10. this.beforeTraceId = beforeTraceId;
    11. // 处理不同集合元素使用不同的 traceId,方便定位日志
    12. String newTraceId = UUID.randomUUID().toString().replaceAll("-", "");
    13. MDC.put("traceId", newTraceId);
    14. } catch (Exception e) {
    15. log.error("TraceExample init error", e);
    16. }
    17. }
    18. @Override
    19. public void close() {
    20. try {
    21. // 集合处理完后恢复遍历集合之前的 traceId
    22. MDC.put("traceId", this.beforeTraceId);
    23. } catch (Exception e) {
    24. log.error("TraceExample init error", e);
    25. }
    26. }
    27. }
    28. 结合 try-catch-finally 在循环语句中使用:
    29. public class BaseTest {
    30. public static void main(String[] args) {
    31. List listData = Arrays.asList("1","2", "3");
    32. for (int i = 0; i < listData.size(); i++) {
    33. // 在处理元素之前设置新的 traceId,元素处理完后再恢复原 traceId。
    34. try (TraceExample ignored = new TraceExample("beforeTraceId")) {
    35. System.out.println("处理元素:" + listData.get(i));
    36. System.out.println("每个元素处理过程中,新的traceId:" + MDC.get("traceId"));
    37. } catch (Exception e) {
    38. throw e;
    39. }
    40. System.out.println("原来的 traceId:" + MDC.get("traceId"));
    41. }
    42. }
    43. }

  • 相关阅读:
    【1++的Linux】之文件(三)
    vue 概述
    Apache Doris FE 元数据常见故障处理
    Ubuntu20.04 安装 Matlab R2021a
    SQL sever2008数据库备份、还原以及库检查
    Day51——JavaScript事件绑定,jQuery类库
    FFmpeg5.1 解码rtsp 并用OpenCV 播放
    叠加态和超级定位:量子世界的奇特现象
    WorkPlus即时通讯app打通业务与生态,实现高效管理与协同
    【字符串与日期的相互转换NSDate Objective-C语言】
  • 原文地址:https://blog.csdn.net/Rookie_CEO/article/details/140123238