关于threadlocal

  在网上看了很多关于threadlocal的文章,感觉大部分说的都是不明其意,关于threadlocal的作用也是众说纷纭,但最多的说法是threadlocal的作用是用于解决多线程并发问题,但自己经过测试,发现并不是那么简单,所以记录下来以供自己日后复习和参考。

     首先要确定的一点是theadlocal的出现并不是为了解决并发问题的,他的作用简单来讲应该是实现线程独有的全局变量这样一个概念。ThreadLocal之所以能使得各线程有各自独立的一个对象,不是通过对什么对象的拷贝或副本来实现的,而是通过每个线程中的new 对象 的操作来创建的对象(initialValue方法),每个线程创建一个,才能保持各线程之间互不干扰。

threadlocal的set方法如下  

/**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

createMap方法

 /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     * @param map the map to store.
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

        可以从上面看到完全没有什么做拷贝或是副本的操作,所以如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 具体验证如下

package EX04;

import java.util.HashMap;

public class Test {
	static ThreadLocal<HashMap<String,String>> stringLocal = new ThreadLocal<HashMap<String,String>>();
	static HashMap<String,String> map = new HashMap<String,String>();

	public static void main(String[] args) throws InterruptedException {
		stringLocal.set(map);
		System.out.println("main >>> " +stringLocal.get().get("key"));
		stringLocal.get().put("key", "value1");
		
		Thread thread1 = new Thread() {
			public void run() {
				stringLocal.set(map);
				System.out.println("thread1 >>> " + stringLocal.get().get("key"));
				stringLocal.get().put("key", "value2");
			};
		};
		
		thread1.start();
		thread1.join();
		System.out.println("main >>> " + stringLocal.get().get("key"));
	}
}
输出:

main >>> null
thread1 >>> value1
main >>> value2
可以看到同一个static变量map,主线程修改可以影响thread1线程,thread1线程也可以影响主线程,验证结束。

最后重申,threadlocal的创建不是为了解决并发问题,而是为了作为线程内的全局变量去使用,比如数据库操作,如果一个事务中涉及多个 DAO 操作,而如果这些DAO中的Connection都是独立创建的话,就没有办法完成一个事务。但是如果放在 ThreadLocal 中就可以解决这个问题,当然他额外的好处就是,在使用过程中,别的线程(用户)也无法调用或者修改这个线程里connection对象。 



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocalJava中一个非常重要的线程封闭技术。它可以让每个线程都拥有自己的变量副本,避免了线程间的竞争和数据泄露问题。在本文中,我们将详细介绍ThreadLocal的定义、用法及其优点。 1. ThreadLocal的定义 ThreadLocalJava中一个用来实现线程封闭技术的类。它提供了一个本地线程变量,可以在多线程环境下使每个线程都拥有自己的变量副本。每个线程都可以独立地改变自己的副本,而不会影响到其他线程的副本。ThreadLocal的实现是基于ThreadLocalMap的,每个ThreadLocal对象都对应一个ThreadLocalMap,其中存储了线程本地变量的值。 2. ThreadLocal的用法 使用ThreadLocal非常简单,只需要创建一个ThreadLocal对象,然后调用其get()和set()方法即可。get()方法用来获取当前线程的变量副本,如果当前线程还没有变量副本,则会创建一个新的副本并返回。set()方法用来设置当前线程的变量副本,如果当前线程已经有了变量副本,则会覆盖原来的副本。 下面是一个简单的例子,演示了如何使用ThreadLocal来实现线程封闭: ```java public class ThreadLocalTest { private static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) throws InterruptedException { new Thread(() -> { threadLocal.set("Thread A"); System.out.println("Thread A: " + threadLocal.get()); }).start(); new Thread(() -> { threadLocal.set("Thread B"); System.out.println("Thread B: " + threadLocal.get()); }).start(); Thread.sleep(1000); System.out.println("Main: " + threadLocal.get()); } } ``` 运行结果如下: ``` Thread A: Thread A Thread B: Thread B Main: null ``` 从输出结果可以看出,每个线程都拥有自己的变量副本,互不影响。而在主线程中,由于没有设置过变量副本,所以返回null。 3. ThreadLocal的优点 ThreadLocal的优点主要体现在以下几个方面: (1)线程安全:ThreadLocal可以避免线程间的竞争和数据泄露问题,每个线程都可以独立地修改自己的变量副本,不会影响其他线程。 (2)高效性:ThreadLocal使用起来非常简单,而且性能也非常高,比如在Web开发中,可以将用户信息存储在ThreadLocal中,从而避免在每个方法中都去查询数据库。 (3)易用性:ThreadLocal的使用非常灵活,可以根据实际需要自由地定义数据类型和访问方式。 总的来说,ThreadLocalJava中一个非常重要的线程封闭技术,可以帮助开发人员避免线程间的竞争和数据泄露问题,提高程序的安全性和性能。在实际开发中,我们应该充分利用ThreadLocal的优点,合理地运用它来解决各种线程安全问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值