将ThreadLocal用于JDBC连接是一种好习惯吗?

时间:2015-10-07 19:46:11

标签: java jdbc thread-local

我不确定我是否得到了这个熟练的ThreadLocals。有时您可以读到,通常的做法是将JDBC连接作为ThreadLocals,以便每个线程获得自己的连接副本。我们假设下面的套接字是JDBC连接。然后我做:

public ThreadLocalSocket() throws IOException {

    Runnable runnable = new Runnable() {

        ThreadLocal<Socket> threadLocal = new ThreadLocal<>();
        @Override
        public void run() {
            try {
                threadLocal.set(new Socket("www.google.com", 80));
            } catch (IOException e) {e.printStackTrace();}

            Thread thread = Thread.currentThread();
            for (int j = 0; j < 10 ; j++) {

                Socket sock = threadLocal.get();
                if (thread.getName().equals("t1")) {
                    if (!sock.isClosed()) {
                        try {
                            sock.close();
                        } catch (IOException e) {e.printStackTrace();}
                    }
                }
                System.out.println("Thread: " + thread.getName()+  ", is closed? " + sock.isClosed() + ", sock hashCode = " + sock.hashCode());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {e.printStackTrace();}
            }
        }
    };

    Thread t1 = new Thread(runnable);
    t1.setName("t1");
    Thread t2 = new Thread(runnable);
    t2.setName("t2");

    t1.start();
    t2.start();
}

为什么我不能在没有ThreadLocals的情况下做到这一点?以下代码片段中的行为与上面的代码示例完全相同:

public ThreadLocalSocket() throws IOException {

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Socket socket = null;
            try {
                socket = new Socket("www.google.com", 80);
            } catch (IOException e) {e.printStackTrace();}

            Thread thread = Thread.currentThread();
            for (int j = 0; j < 10 ; j++) {
                if (thread.getName().equals("t1")) {
                    if (!socket.isClosed()) {
                        try {
                            socket.close();
                        } catch (IOException e) {e.printStackTrace();}
                    }
                }
                System.out.println("Thread: " + thread.getName()+  ", is closed? " + socket.isClosed() + ", socket hashCode = " + socket.hashCode());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {e.printStackTrace();}
            }
        }
    };

    Thread t1 = new Thread(runnable);
    t1.setName("t1");
    Thread t2 = new Thread(runnable);
    t2.setName("t2");

    t1.start();
    t2.start();
}

1 个答案:

答案 0 :(得分:3)

是的,在您的使用案例中,它很无用。

javadoc of ThreadLocal

  

ThreadLocal实例通常是类中的私有静态字段   希望将状态与线程相关联(例如,用户ID或   交易ID)。

典型的用例是将ThreadLocal作为一种全局成员,这样您就不必传递引用的值。您通过一些static方法公开它,并且您编写的每一段代码都可以访问它,而无需每次都注入它。

例如,Spring MVC提供了类RequestContextHolder,它对ThreadLocal对象保持ServletRequest引用。由于servlet容器通常(即非异步模式)通过在单个线程中处理请求来工作,而不是必须将ServletRequest传递给处理流程中的每个组件,因此Spring在{ {1}}和其他组件可以通过RequestContextHolder辅助方法访问它(实际上只是请求的属性)。