码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2014-12-24 20:04:27      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

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为线程生成唯一标识及实现原理

标签:

原文地址:http://www.cnblogs.com/hellocyc/p/4183005.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!