大浪网站建设/怎么在百度上设置自己的门店
1.简单介绍
在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
下面是示例:
public class ThreadLocalTest {/*1通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 */private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() { public Integer initialValue() { return 0; } }; /*2获取下一个序列值 */public int getNextNum() { seqNum.set(seqNum.get() + 1); return seqNum.get(); } public static void main(String args[]){System.out.println("ThreadLocalTest start");ThreadLocalTest sn = new ThreadLocalTest(); /*3个线程共享sn,各自产生序列号 */TestClient t1 = new TestClient(sn); TestClient t2 = new TestClient(sn); TestClient t3 = new TestClient(sn); t1.start(); t2.start(); t3.start(); }private static class TestClient extends Thread { private ThreadLocalTest sn; public TestClient(ThreadLocalTest sn) { this.sn = sn; } public void run() { for (int i = 0; i < 3; i++) { /*4每个线程打出3个序列值 */System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn[" + sn.getNextNum() + "]"); } } }
}
使用例子:
/**sdf有全局变量线程不安全,用ThreadLocal提供线程安全的sdf*/public static final ThreadLocal<DateFormat> SDF = new ThreadLocal<DateFormat>() {@Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");}};
2.比较优秀的使用例子2(重要):
public class Port implements IThreadCase{//当前线程的Port实例private final static ThreadLocal<Port> portCurrent = new ThreadLocal<>();//线程管理类private final ThreadHandler thread;public Port(){this.thread = new ThreadHandler(this);}/** 开始 */public Port startup() {// 启动独立线程this.thread.setName(toString());this.thread.startup();return this;}/** 结束 */public void stop() {if (thread == null)return;// 停止独立线程this.thread.cleanup();}/** 获取当前线程的Port实例 */@SuppressWarnings("unchecked")public static <T extends Port> T getCurrent() {return (T) portCurrent.get();}@Overridepublic void caseStart() {portCurrent.set(this);}@Overridepublic void caseStop() {portCurrent.set(null);}
}
3. ThreadLocal会造成内存泄漏吗?
不同线程反复对ThreadLocal设置自己的值,线程会自己结束,但是没有对ThreadLocal存储本线程的内容做移除,会造成内存泄漏吗。
答案是不会的。
示例代码:
public class ThreadLocalTest {public static final int _10MB = 1024 * 1024 * 10;public static ThreadLocal<Object> threadLocal = new ThreadLocal(){@Overridepublic Object initialValue(){return null;}};public static void main(String args[]){System.out.println();for(;;){new Thread(){@Overridepublic void run() {byte[] data = new byte[_10MB];threadLocal.set(data);}}.start();ThreadTool.sleep(1000);System.out.println(Sys.getJVMStatus());}}
}
运行结果:
maxM=3641 MB, totalM=245.5 MB, freeM=231.66 MB, usedM=13.84 MB
maxM=3641 MB, totalM=245.5 MB, freeM=220.38 MB, usedM=25.12 MB
maxM=3641 MB, totalM=245.5 MB, freeM=209.1 MB, usedM=36.4 MB
maxM=3641 MB, totalM=245.5 MB, freeM=197.82 MB, usedM=47.68 MB
maxM=3641 MB, totalM=245.5 MB, freeM=186.54 MB, usedM=58.96 MB
maxM=3641 MB, totalM=245.5 MB, freeM=233.51 MB, usedM=11.99 MB
maxM=3641 MB, totalM=245.5 MB, freeM=222.22 MB, usedM=23.28 MB
maxM=3641 MB, totalM=245.5 MB, freeM=211.58 MB, usedM=33.92 MB
maxM=3641 MB, totalM=245.5 MB, freeM=200.94 MB, usedM=44.56 MB
maxM=3641 MB, totalM=245.5 MB, freeM=190.3 MB, usedM=55.2 MB
maxM=3641 MB, totalM=245.5 MB, freeM=232.87 MB, usedM=12.63 MB
maxM=3641 MB, totalM=245.5 MB, freeM=221.16 MB, usedM=24.34 MB
maxM=3641 MB, totalM=245.5 MB, freeM=209.88 MB, usedM=35.62 MB
maxM=3641 MB, totalM=245.5 MB, freeM=198.6 MB, usedM=46.9 MB
maxM=3641 MB, totalM=245.5 MB, freeM=187.32 MB, usedM=58.18 MB
maxM=3641 MB, totalM=245.5 MB, freeM=233.56 MB, usedM=11.94 MB
maxM=3641 MB, totalM=245.5 MB, freeM=222.65 MB, usedM=22.85 MB
maxM=3641 MB, totalM=245.5 MB, freeM=212.01 MB, usedM=33.49 MB
maxM=3641 MB, totalM=245.5 MB, freeM=201.37 MB, usedM=44.13 MB
maxM=3641 MB, totalM=245.5 MB, freeM=190.73 MB, usedM=54.77 MB
maxM=3641 MB, totalM=245.5 MB, freeM=234.2 MB, usedM=11.3 MB
maxM=3641 MB, totalM=245.5 MB, freeM=222.74 MB, usedM=22.76 MB
maxM=3641 MB, totalM=245.5 MB, freeM=211.46 MB, usedM=34.04 MB
maxM=3641 MB, totalM=245.5 MB, freeM=200.18 MB, usedM=45.32 MB
maxM=3641 MB, totalM=245.5 MB, freeM=188.9 MB, usedM=56.6 MB
maxM=3641 MB, totalM=234.5 MB, freeM=222.59 MB, usedM=11.91 MB
maxM=3641 MB, totalM=234.5 MB, freeM=211.23 MB, usedM=23.27 MB
原因分析:
我们看下get和Set
public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}
ThreadLocal.ThreadLocalMap.Entry是啥?
/*** ThreadLocalMap is a customized hash map suitable only for* maintaining thread local values. No operations are exported* outside of the ThreadLocal class. The class is package private to* allow declaration of fields in class Thread. To help deal with* very large and long-lived usages, the hash table entries use* WeakReferences for keys. However, since reference queues are not* used, stale entries are guaranteed to be removed only when* the table starts running out of space.*/static class ThreadLocalMap {/*** The entries in this hash map extend WeakReference, using* its main ref field as the key (which is always a* ThreadLocal object). Note that null keys (i.e. entry.get()* == null) mean that the key is no longer referenced, so the* entry can be expunged from table. Such entries are referred to* as "stale entries" in the code that follows.*/static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}
因为继承了
WeakReference<?>
所以是弱引用,每次GC的时候总会被回收