ThreadLocal怎么在Java中使用

  介绍

今天就跟大家聊聊有关ThreadLocal怎么在Java中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。


ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

这句话从字面上看起来很容易理解,但是真正理解并不是那么容易。

我们还是先来看一个例子:

类ConnectionManager {
  
  私有静态连接连接=零;
  
  公共静态连接openConnection () {
  如果(连接==null) {
  连接=DriverManager.getConnection ();
  }
  返回连接;
  }
  
  公共静态孔隙closeConnection () {
  如果(连接!=null)
  connect.close ();
  }
  }

假设有这样一个数据库链接管理类,这段代码在单线程中使用是没有任何问题的,但是如果在多线程中使用呢?很显然,在多线程中使用会存在线程安全问题:

第一,这里面的2个方法都没有进行同步,很可能在openConnection方法中会多次创建连接;

第二,由于连接是共享变量,那么必然在调用连接的地方需要使用到同步来保障线程安全,因为很可能一个线程在使用连接进行数据库操作,而另外一个线程调用closeConnection关闭链接。

所以出于线程安全的考虑,必须将这段代码的两个方法进行同步处理,并且在调用连接的地方需要进行同步处理。

这样将会大大影响程序执行效率,因为一个线程在使用连接进行数据库操作的时候,其他线程只有等待。

那么大家来仔细分析一下这个问题,这地方到底需不需要将连接变量进行共享?事实上,是不需要的。假如每个线程中都有一个连接变量,各个线程之间对连接变量的访问实际上是没有依赖关系的,即一个线程不需要关心其他线程是否对这个连接进行了修改的。

到这里,可能会有朋友想到,既然不需要在线程之间共享这个变量,可以直接这样处理,在每个需要使用数据库连接的方法中具体使用时才创建数据库链接,然后在方法调用完毕再释放这个连接。比如下面这样:

类ConnectionManager {
  
  私人连接连接=零;
  
  公共连接openConnection () {
  如果(连接==null) {
  连接=DriverManager.getConnection ();
  }
  返回连接;
  }
  
  公共空间closeConnection () {
  如果(连接!=null)
  connect.close ();
  }
  }
  
  
  Dao类{
  公共空间插入(){
  ConnectionManager ConnectionManager=new ConnectionManager ();
  连接连接=connectionManager.openConnection ();//使用连接进行操作
  
  connectionManager.closeConnection ();
  }
  }

这样处理确实也没有任何问题,由于每次都是在方法内部创建的连接,那么线程之间自然不存在线程安全问题。但是这样会有一个致命的影响:导致服务器压力非常大,并且严重影响程序执行性能。由于在方法中需要频繁地开启和关闭数据库连接,这样不尽严重影响程序执行效率,还可能导致服务器压力巨大。

那么这种情况下使用ThreadLocal是再适合不过的了,因为ThreadLocal在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。

但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。


在上面谈到了对ThreadLocal的一些理解,那我们下面来看一下具体ThreadLocal是如何实现的。

先了解一下ThreadLocal类提供的几个方法:

ThreadLocal怎么在Java中使用