ThreadLocal(一)设计ThreadLocal的目的
Posted zhangjin1120
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreadLocal(一)设计ThreadLocal的目的相关的知识,希望对你有一定的参考价值。
ThreadLocal(一)设计ThreadLocal的目的
ThreadLoca(二)Looper中ThreadLocal的使用
先看看ThreadLocal类的文档注释:
/**
* This class provides thread-local variables. These variables differ from
* their normal counterparts in that each thread that accesses one (via its
* @code get or @code set method) has its own, independently initialized
* copy of the variable. @code 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).
*
* <p>For example, the class below generates unique identifiers local to each
* thread.
* A thread's id is assigned the first time it invokes @code ThreadId.get()
* and remains unchanged on subsequent calls.
* <pre>
* import java.util.concurrent.atomic.AtomicInteger;
*
* public class ThreadId
* // Atomic integer containing the next thread ID to be assigned
* private static final AtomicInteger nextId = new AtomicInteger(0);
*
* // Thread local variable containing each thread's ID
* private static final ThreadLocal<Integer> threadId =
* new ThreadLocal<Integer>()
* @Override protected Integer initialValue()
* return nextId.getAndIncrement();
*
* ;
*
* // Returns the current thread's unique ID, assigning it if necessary
* public static int get()
* return threadId.get();
*
*
* </pre>
* <p>Each thread holds an implicit reference to its copy of a thread-local
* variable as long as the thread is alive and the @code ThreadLocal
* instance is accessible; after a thread goes away, all of its copies of
* thread-local instances are subject to garbage collection (unless other
* references to these copies exist).
*
翻译过来:
此类提供线程本地变量。这些变量不同于线程的普通对应变量,因为访问一个变量的每个线程(通过其get或set方法)都有自己的、独立初始化的变量副本。ThreadLocal实例通常是类中的private static 字段,这个字段希望将状态与线程(例如,用户ID或事务ID)关联的类中。
例如,下面的类为每个线程生成本地的唯一标识符。
一个线程的id, 在第一次调用时被分配,在随后的调用中保持不变。
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadId
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>()
@Override protected Integer initialValue()
return nextId.getAndIncrement();
;
// Returns the current thread's unique ID, assigning it if necessary
public static int get()
return threadId.get();
只要线程处于活动状态且ThreadLocal实例可访问,每个线程都持有对其线程局部变量副本的隐式引用;线程消失后,其线程本地实例的所有副本都将接受垃圾收集(除非存在对这些副本的其他引用)。
java程序中,某个线程的非私有成员变量是可以被其他线程访问和修改的。如下:
public class ThreadTest
public static void main(String[] args)
ThreadB b = new ThreadB();
new Thread(new Runnable()
@Override
public void run()
b.publicName ="pubThreadBBB";
b.protectedName = "proThreadBBB";
b.defaultName = "defThreadBBB";
System.out.println("将 ThreadB的名字修改为:" + b.defaultName);
).start();
//新建一个ThreadB.java文件
public class ThreadB extends Thread
public String publicName = "ThreadB";
protected String protectedName = "ThreadB";
String defaultName = "ThreadB";
private String privateName = "ThreadB";
如果想要某个线程私有的变量,不能被其他线程访问和修改,怎么办?
用private修饰或者设为默认,不就好了。
还真就是这样,我们看看Thread的源码:
public class Thread implements Runnable
...
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
...
注释翻译过来就是:与此线程相关的ThreadLocal值。此映射由ThreadLocal类维护。所以:
设计ThreadLocal的目的,是为了存储线程私有的变量,其他线程无法访问,也就是实现了线程封闭。
如何防止其他线程,修改线程本地变量?
将ThreadB的写法,修改如下:
public class ThreadB extends Thread
//ThreadLocal的注释中,建议用private static修饰
private static ThreadLocal<String> tl = new ThreadLocal<>();
public ThreadB(String name)
super();
tl.set(name);
public String getNam()
return tl.get(); //ThreadLocal内部有判空处理
这样,其他线程,就访问不能修改name变量了。
如果线程私有的变量有许多,其是不同类型,怎么办?
把多个变量,写在一个类里面,再把这个类作为ThreadLocal的泛型。例如:android SDK中,Looper内部包含了MessageQueue,MessageQueue就是线程私有的。
以上是关于ThreadLocal(一)设计ThreadLocal的目的的主要内容,如果未能解决你的问题,请参考以下文章