首页 > 代码库 > 用ThreadLocal为线程生成唯一标识及实现原理

用ThreadLocal为线程生成唯一标识及实现原理

1、在多线程编程中,有时候需要自动为每个启动的线程生成一个唯一标识,这个时候,通过一个ThreadLocal变量来保存每个线程的标识是最有效、最方便的方式了。

2、ThreadLocal 实例通常是类中的私有静态字段

3、在构建ThreadLocal的时候,通过覆盖子类的方法来改写序号。从而达到为每个线程生成序号的目的。

 

import java.util.Collections;import java.util.HashMap;import java.util.Map;/** * 一个多线程对象,其中有个私有变量SerialNum,用来保存该对象线程的序号  * @author yinchuan.chen * */class MultiThreadObject extends Thread {     //线程序号变量     private SerialNum  serialNum;     public MultiThreadObject(SerialNum  serialNum) {         //初始化线程序号保存变量         this.serialNum = serialNum;     }     /**      * 一个示意性的多线程业务方法      */     public void run() {         System.out.println("线程" + Thread.currentThread().getName() + "的序号为" + serialNum.getNextNum());     } }/** * 一个示意性的ThreadLocal实现,与JDK中ThreadLocal的API对等  * @author yinchuan.chen * */class SimpleThreadLocal {     //一个线程Map,用来存放线程和其对应的变量副本     private Map threadMap = Collections.synchronizedMap(new HashMap());     public void set(Object object) {         threadMap.put(Thread.currentThread(), object);     }     public Object get() {         Thread currentThread = Thread.currentThread();         Object obj = threadMap.get(currentThread);         if (obj == null && !threadMap.containsKey(currentThread)) {             obj = initialValue();             threadMap.put(currentThread, obj);         }         return obj;     }     public void remove() {         threadMap.remove(Thread.currentThread());     }     protected Object initialValue() {         return null;     } }/** * 线程序号标识生成工具  * @author yinchuan.chen * */class SerialNum {     //类级别的线程编号变量,指向下一个线程的序号     private static Integer nextNum = 0;     //定义一个ThreadLocal变量,存放的是Integer类型的线程序号 //    private static ThreadLocal<Integer> threadNo = new ThreadLocal<Integer>() {     private static SimpleThreadLocal threadNo = new SimpleThreadLocal() {         //通过匿名内部类的方式定义ThreadLocal的子类,覆盖initialValue()方法         public synchronized Integer initialValue() {             return nextNum++;         }     };     /**      * 获取线程序号      *      * @return 线程序号      */     public int getNextNum() {         return (Integer)threadNo.get();     } }public class TestTreadLocal {     public static void main(String[] args) {         SerialNum serialNum = new SerialNum();         MultiThreadObject m1 = new MultiThreadObject(serialNum);         MultiThreadObject m2 = new MultiThreadObject(serialNum);         MultiThreadObject m3 = new MultiThreadObject(serialNum);         MultiThreadObject m4 = new MultiThreadObject(serialNum);         m1.start();         m2.start();         m3.start();         m4.start();         //下面的test方法是在主线程中,当前线程是         testMainThread();     }     public static void testMainThread(){         SerialNum serialNum = new SerialNum();         System.out.println("主线程的序号为"+serialNum.getNextNum());         SerialNum serialNum2 = new SerialNum();         System.out.println("主线程的序号为"+serialNum2.getNextNum());     } }

 

用ThreadLocal为线程生成唯一标识及实现原理