用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()); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。