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. Tomcat学习 HttpConnector和HttpProcessor启动流程和线程交互

    一.tomat启动流程 1.启动HttpConnector connector等待连接请求,只负责接受socket请求,具体处理过程交给HttpProcessor处理. tomcat用户只能访问到co ...

  2. J2EE maven pom.xml常用的jar包

    新建一个maven webapp工程,默认的pom.xml文件如下: <project xmlns="http://maven.apache.org/POM/4.0.0" x ...

  3. Postgres数据库基本介绍

    最近一直在做一个和PostgreSQL数据库相关的项目,把自己在这个过程中学习的知识记录下来.关于PostgreSQL数据库网上已经有太多的相关介绍了,为了博文的系统性还是先看一下维基百科对Postg ...

  4. Web TreeView 加载级联数据

    protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { dt = BLL.GetTable(); LoadL ...

  5. C++之路进阶——poj2104(K-th Number)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 44537   Accepted: 14781 Ca ...

  6. bzoj2333 [SCOI2011]棘手的操作

    用set维护每个联通块里的最值,multiset维护所有块里的最值,并查集维护连通性,然后随便搞搞就行了,合并时候采用启发式合并.复杂度O(nlognlogn),大概勉强过的程度,反正跑的很慢就是了. ...

  7. ligerui_ligerTree_002_利用JavaScript代码配置ligerTree节点

    利用JavaScript代码配置ligerTree节点: 源码地址:http://download.csdn.net/detail/poiuy1991719/8571255 效果图: <%@ p ...

  8. 多屏复杂动画CSS技巧三则(转载)

    本文转载自: 经验分享:多屏复杂动画CSS技巧三则

  9. RMAN备份演练初级篇

    前面我们已经知道了如何进入rman,以及rman的一些基本命令,相信大家定会觉着rman操作的简单,事实也确实如此,但万不要因此小视rman的强大,简单往往意味着灵活,灵活对于那些有心人则意味着主动权 ...

  10. java.lang.UnsatisfiedLinkError: no sapjco3 in java.library.path

    1.system32添加sapjco3.dll 2.tomcat bin下添加sapjco3.dll 3.项目中添加sapjco3.jar 包