你不知道的多线程ThreadLocal
2023-04-06 14:46:22
Threadlocal是线程的局部变量,用于编写多线程序,对解决多线程序并发问题有一定的启发作用。早在JDK在1.2版本中提供java.lang.ThreadLocal,Threadlocal为解决多线程序并发问题提供了新的思路。使用这个工具可以简单地编写一个漂亮的多线程序。事实上,很多人不知道Threadlocal,被它的英文名字误导,误以为是本地线程。让我们谈谈你不知道的多线程ThreadLocal。
多线程局部变量(ThreadLocal)其实功能很简单,为每个使用该变量的线程提供一个变量值副本,使得每个线程都可以独立地改变自己的副本,而不会与其他线程的副本发生冲突。从线程的角度来看,似乎每个线程都有这个变量。从而完美地解决了多线程序的并发性问题。
那么如何创建一个Threadlocal变量呢?只需要一行简单的代码:
private ThreadLocalmyThreadLocal= new ThreadLocal();
从这一行的简单代码中我们可以看出,通过这段代码实例化ThreadLocal对象。我们只需要一个实例对象,也不需要知道它是由哪个线程实例化的。虽然所有线程都可以访问这个threadlocal实例,但每个线程只能访问通过调用threadlocal设置的set()方法设置的值。即使两个不同的线程在同一个ThreadLocal对象上设置不同的值,他们仍然无法访问对方的值。
下一个问题我们抛出:如何访问Threadlocal变量?
一旦创建了一个Threadlocal变量,您可以通过以下代码设置需要保存的值:
myThreadLocal.set(“A thread local value”);
然后可以通过以下方法读取和保存ThreadLocal变量值:
String ThreadLocalvalue = (String) myThreadLocal.get();
get()方法返回object对象,set()对象需要输入object类型的参数。
同时我们可以创建指定的一般类型Threadlocal对象,因此我们不需要每次强制转换使用get()方法返回的值。由于设置在threadlocal对象中的值只能通过设置该值的线程访问,因此在threadlocal对象上不能使用set()方法保存初始值,并且该初始值可以通过所有线程访问。
但是我们可以通过创建一个来创建一个Threadlocal子类,重写initialvalue()方法,为Threadlocal对象指定初始值。
下面给大家举一下一个完整的可执行的Threadlocal例子:
上述例子创建了一个例子MyRunnable实例,并将该实例作为参数分别传递给了两个线程。两个线程分别执行。run()方法,并且在ThreadLocal实例中保存了不同的值。如果他们访问的不是threadlocal对象,并且调用的set()方法同步,则第二个线程将覆盖第一个线程设置的值。但是,由于他们访问的是ThreadLocal对象,这两个线程都看不到对方保存的值。也就是说,他们存取的是两个不同的值。
与其他同步机制相比,ThreadLocal有什么优势?Threadlocal等所有同步机制都是为了解决多线程中同一变量的访问冲突。在普通同步机制中,多线程通过对象锁定安全访问同一变量。此时,变量由多个线程共享。使用这种同步机制需要仔细分析变量何时读写、何时锁定对象、何时释放对象锁等。所有这些都是由多个线程共享资源造成的。Threadlocal将从另一个角度解决多线程的并发访问。Threadlocal将维护与每个线程绑定的变量副本,以隔离多个线程的数据。每个线程都有自己的变量副本,因此没有必要同步变量。Threadlocal提供线程安全共享对象。在编写多线程代码时,可以将不安全的整个变量包装到Threadlocal中,也可以将对象的特定线程状态包装到Threadlocal中。