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为线程生成唯一标识及实现原理的更多相关文章

  1. JAVA UUID 生成唯一标识

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want 需求 项目在设计表的时候,要处理并发多的一些数据 ...

  2. Python标准库 -- UUID模块(生成唯一标识)

    UUID是什么: UUID: 通用唯一标识符 ( Universally Unique Identifier ),对于所有的UUID它可以保证在空间和时间上的唯一性,也称为GUID,全称为: UUID ...

  3. 用SQL语句生成唯一标识

    以前都是在代码中生成GUID值,然后保存到数据库中去,今天发现用sql也能生成GUID值,觉得很新奇,所以记下来. sellect newid();  //得到的即为GUID值 此sql内置函数返回的 ...

  4. ORACLE生成唯一标识函数

    -- Create tablecreate table TAB_TEST( id VARCHAR2(40) not null, fxnum VARCHAR2(40)) ---------------- ...

  5. 转:C#生成唯一值的方法汇总

    这篇文章主要介绍了C#生成唯一值的方法汇总,有需要的朋友可以参考一下 生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试: 一.在 .NET ...

  6. C#生成唯一值的方法汇总

    生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试: https://www.cnblogs.com/xinweichen/p/4287640 ...

  7. Flask中的ThreadLocal本地线程,上下文管理

    先说一下和flask没有关系的: 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程对同一块 ...

  8. [转]iOS设备唯一标识探讨

    转自:http://www.jianshu.com/p/b83b0240bd0e iOS设备唯一标识探讨 为了统计和检测应用的使用数据,几乎每家公司都有获取唯一标识的业务需求,在iOS5以前获取唯一标 ...

  9. iOS获取设备唯一标识的各种方法?IDFA、IDFV、UDID分别是什么含义?

    一.UDID (Unique Device Identifier) UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和 ...

随机推荐

  1. 学习OpenCV——Kmean(C++)

    从前也练习使用过OpenCV的Kmean算法,但是那版本低,而且也是基于C的开发.这两天由于造论文的需要把它重新翻出来在研究一下C++,发现有了些改进 kmeans C++: doublekmeans ...

  2. PostgreSQL Errors and Messages

    使用RAISE语句来报告消息并抛出错误 RAISE [ level ] ’format’ [, expression [, ... ]] [ USING option = expression [, ...

  3. [转] java书籍(给Java程序猿们推荐一些值得一看的好书 + 7本免费的Java电子书和教程 )

    7本免费的Java电子书和教程 1. Thinking in Java (Third Edition) 本书的作者是Bruce Eckel,它一直都是Java最畅销的免费电子书.这本书可以帮助你系统的 ...

  4. [转]JVM内幕:Java虚拟机详解

    本文由 ImportNew - 挖坑的张师傅 翻译自 jamesdbloom.欢迎加入翻译小组.转载请见文末要求. 这篇文章解释了Java 虚拟机(JVM)的内部架构.下图显示了遵守Java SE 7 ...

  5. HDU 4063 Aircraft(计算几何)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063 Description You are playing a flying game. In th ...

  6. sql查询 所有被锁定的表

    --sql查询  所有被锁定的表 select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName ...

  7. mongodb聚合内存不足解决方案

    原因:mongodb每一个文档默认只有16M.聚合的结果是一个BSON文档,当超过16M大小时,就会报内存不够错误. exceeded memory limit for $group.but didn ...

  8. 夺命雷公狗—angularjs—24—extend继承对象

    我们的angularjs中也是给我们留下了方法来做继承的,那么他就是传授中的extend... 不过要如下所示,第二个参数是继承到第一个对象里面的... <!DOCTYPE html> & ...

  9. 夺命雷公狗ThinkPHP项目之----企业网站7之栏目的修改(主要用模型来验证字段)

    我们照老,在控制器里面先查出我们所需要用到的数据: 然后直接遍历到模版上即可: 然后再开始写提交过来的数据处理问题(注意一定要接收修改页面通过隐藏域)而且我们刚才已经写好我们的model层了,所以直接 ...

  10. MyEclipse启动失败

    日志的一部分: !SESSION 2014-09-24 11:47:03.156 -----------------------------------------------eclipse.buil ...