java面试系列--J2SE基础(九)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weisong530624687/article/details/79431101

25. ThreadLocal的设计理念与作用。

官方JDK7释义:

以下节选自官方api中释义:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

For example, the class below generates unique identifiers local to each thread. A thread's id is assigned the first time it invokes ThreadId.get() and remains unchanged on subsequent calls.

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

例如,以下类生成对每个线程唯一的局部标识符。 线程 ID 是在第一次调用 UniqueThreadIdGenerator.getCurrentThreadId() 时分配的,在后续调用中不会更改。

  import java.util.concurrent.atomic.AtomicInteger;

 public class UniqueThreadIdGenerator {

     private static final AtomicInteger uniqueId = new AtomicInteger(0);

     private static final ThreadLocal < Integer > uniqueNum = 
         new ThreadLocal < Integer > () {
             @Override protected Integer initialValue() {
                 return uniqueId.getAndIncrement();
         }
     };
 
     public static int getCurrentThreadId() {
         return uniqueId.get();
     }
 } // UniqueThreadIdGenerator
 
每个线程都保持对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。


ThreadLocal的作用

综上概括来讲有以下特性:
- 不同线程访问时取得不同的值 
- 任意线程对它的改变不影响其他线程

当多个线程要对同一个资源进行共享的时候,而且要求每个线程对资源的处理又是相互独立的,互不影响的,就可以使用ThreadLocal。

ThreadLocal最大的作用就是把线程共享变量转换成线程本地变量,实现线程之间的隔离。


代码实例:

package com.ws.threadlocal;
/**
 * 构建一个本地ThreadLoca属性
 * @author WeiS
 *
 */
public class MyThreadLocal {
	
	private ThreadLocal<String> myTreadLocal = new ThreadLocal<String>() {
		@Override
		protected String initialValue() {
			return super.initialValue();
		}
	};
	
	public String getNextValue() {
		myTreadLocal.set(myTreadLocal.get()+"aa");
		return myTreadLocal.get();
	}

}
package com.ws.threadlocal;
/**
 * 测试demo,内含一个MyThreadLocal对象
 * @author WeiS
 *
 */
public class ThreadLocalDemo extends Thread{
	
	private MyThreadLocal myThreadLocal;
	
	public ThreadLocalDemo(MyThreadLocal threadLocal) {
		this.myThreadLocal = threadLocal;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + myThreadLocal.getNextValue()); 
		}
	}
	

}
package com.ws.threadlocal;

public class Main {

	public static void main(String[] args) {
		MyThreadLocal myThreadLocal = new MyThreadLocal(); 
        Thread t1 = new ThreadLocalDemo(myThreadLocal); 
        Thread t2 = new ThreadLocalDemo(myThreadLocal); 
        Thread t3 = new ThreadLocalDemo(myThreadLocal); 
        Thread t4 = new ThreadLocalDemo(myThreadLocal); 
        t1.start(); 
        t2.start(); 
        t3.start(); 
        t4.start(); 
	}

}



打赏

如果觉得我的文章对你有帮助,有钱就捧个钱场,没钱就捧个人场,欢迎点赞或转发 ,并请注明原出处,谢谢....








猜你喜欢

转载自blog.csdn.net/weisong530624687/article/details/79431101