加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

如何强制Java线程关闭线程本地数据库连接

发布时间:2020-12-14 05:39:37 所属栏目:Java 来源:网络整理
导读:当使用线程本地数据库连接时,线程存在时需要关闭连接. 我只能在覆盖调用线程的run()方法的情况下才能做到这一点.即使这不是一个很好的解决方案,因为在退出时,我不知道连接是否曾被该线程打开. 问题其实是一般的:如何强制线程在线程本地对象退出时调用一些fi
当使用线程本地数据库连接时,线程存在时需要关闭连接.

我只能在覆盖调用线程的run()方法的情况下才能做到这一点.即使这不是一个很好的解决方案,因为在退出时,我不知道连接是否曾被该线程打开.

问题其实是一般的:如何强制线程在线程本地对象退出时调用一些finalization方法.

我查看了java 1.5的源码,发现线程本地地图设置为null,最终会导致垃圾回收调用finalize(),但我不想指望垃圾收集器.

以下重写似乎是不可避免的,以确保数据库连接已关闭:

@Override 
public void remove() {
    get().release(); 
    super.remove(); 
}

其中release()关闭数据库连接,如果已经打开.但是我们不知道线程是否曾经使用过这个线程本地的.如果这个线程没有调用get(),那么在这里将耗费很多精力:ThreadLocal.initialValue()将被调用,这个线程上将创建一个map.

根据Thorbj?rn的评论进一步澄清和举例:

java.lang.ThreadLocal是绑定到线程的对象的一种工厂类型.此类型具有对象的getter和工厂方法(通常由用户编写).当getter被调用时,它调用factory方法,只有当它从未被这个线程调用过.

使用ThreadLocal允许开发人员将资源绑定到线程,即使线程代码是由第三方编写的.

例:
说我们有一个名为MyType的资源类型,我们希望每个线程只有一个.

在使用类中定义:
private static ThreadLocal resourceFactory = new ThreadLocal(){
@override
protected MyType initialValue(){
返回新的MyType();
}
}

在本课程中使用本地上下文:
public void someMethod(){
MyType resource = resourceFactory.get();
resource.useResource();
}

get()可以在调用线程的生命周期中调用initialValue()一次.此时,MyType的实例被实例化并绑定到此线程.随后通过此线程调用get()再次引用此对象.

经典使用示例是当MyType是一些线程不安全的文本/日期/ xml格式化程序时.

但是,这样的格式化程序通常不需要被释放或关闭,数据库连接和我正在使用java.lang.ThreadLocal每个线程都有一个数据库连接.

我看到它的方式,java.lang.ThreadLocal几乎是完美的.几乎因为如果调用线程属于第三方应用程序,则无法保证资源的关闭.

我需要你的脑筋:通过扩展java.lang.ThreadLocal我设法为每个线程绑定一个数据库连接,因为它是独占使用 – 包括我无法修改或覆盖的线程.我设法确保连接关闭,以防线程在未捕获的异常情况下死亡.

在正常线程退出的情况下,垃圾回收器关闭连接(因为MyType覆盖finalize()).实际上它发生得很快,但这并不理想.

如果我有我的方式,那么在java.lang.ThreadLocal中会有另一种方法:

protected void release() throws Throwable {}

如果这个方法存在于java.lang.ThreadLocal,在任何线程退出/死亡时由JVM调用,然后在我自己的覆盖中,我可以关闭我的连接(救赎者将来到锡安).

在没有这种方法的情况下,我正在寻找另一种方式来确认关闭.一种不依赖于JVM垃圾收集的方式.

谢谢

解决方法

如果你是一个敏感的处置,现在看看.

我不会指望这个比例很好;它有效地使系统中的线程数增加了一倍.可能有一些可以接受的用例.

public class Estragon {
  public static class Vladimir {
    Vladimir() { System.out.println("Open"); }
    public void close() { System.out.println("Close");}
  }

  private static ThreadLocal<Vladimir> HOLDER = new ThreadLocal<Vladimir>() {
    @Override protected Vladimir initialValue() {
      return createResource();
    }
  };

  private static Vladimir createResource() {
    final Vladimir resource = new Vladimir();
    final Thread godot = Thread.currentThread();
    new Thread() {
      @Override public void run() {
        try {
          godot.join();
        } catch (InterruptedException e) {
          // thread dying; ignore
        } finally {
          resource.close();
        }
      }
    }.start();
    return resource;
  }

  public static Vladimir getResource() {
    return HOLDER.get();
  }
}

更好的错误处理等作为实施者的练习.

您还可以查看跟踪线程/资源的ConcurrentHashMap与另一个线程轮询isAlive.但是解决方案是绝望的最后手段 – 对象可能最终被检查太频繁或太少.

我不能想到任何不涉及仪器的事情. AOP可能工作.

连接池将是我最喜欢的选择.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读