用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为线程生成唯一标识及实现原理的更多相关文章
- JAVA UUID 生成唯一标识
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want 需求 项目在设计表的时候,要处理并发多的一些数据 ...
- Python标准库 -- UUID模块(生成唯一标识)
UUID是什么: UUID: 通用唯一标识符 ( Universally Unique Identifier ),对于所有的UUID它可以保证在空间和时间上的唯一性,也称为GUID,全称为: UUID ...
- 用SQL语句生成唯一标识
以前都是在代码中生成GUID值,然后保存到数据库中去,今天发现用sql也能生成GUID值,觉得很新奇,所以记下来. sellect newid(); //得到的即为GUID值 此sql内置函数返回的 ...
- ORACLE生成唯一标识函数
-- Create tablecreate table TAB_TEST( id VARCHAR2(40) not null, fxnum VARCHAR2(40)) ---------------- ...
- 转:C#生成唯一值的方法汇总
这篇文章主要介绍了C#生成唯一值的方法汇总,有需要的朋友可以参考一下 生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试: 一.在 .NET ...
- C#生成唯一值的方法汇总
生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试: https://www.cnblogs.com/xinweichen/p/4287640 ...
- Flask中的ThreadLocal本地线程,上下文管理
先说一下和flask没有关系的: 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程对同一块 ...
- [转]iOS设备唯一标识探讨
转自:http://www.jianshu.com/p/b83b0240bd0e iOS设备唯一标识探讨 为了统计和检测应用的使用数据,几乎每家公司都有获取唯一标识的业务需求,在iOS5以前获取唯一标 ...
- iOS获取设备唯一标识的各种方法?IDFA、IDFV、UDID分别是什么含义?
一.UDID (Unique Device Identifier) UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和 ...
随机推荐
- mongodb远程连接以及备份、还原、导出、导入
一.远程连接mongodb 连接命令:mongo -u username -p pwd 192.168.41.215:27017/database(用户名对应的数据库) 二.mongodump备份数据 ...
- php:mysqli扩展
mysqli功能概述:http://php.net/manual/zh/mysqli.summary.php 代码(基本的用法):貌似可以防止sql注入 $root = "root" ...
- 脚本:SQLServer 2008 生成某数据库中的所有索引创建脚本
--1. get all indexes from current db, place in temp table select schemaName = s.name, tablename = ob ...
- PostgreSQL Replication之第十一章 使用Skytools(1)
向您介绍了 Slony 之后,我们将介绍另外一种流行的复制工作.Skytools 是一个最初有 Skype 开发的软件包,它有多种用途.Skytools 不只是一个单一的程序,而且是一个工具与服务的集 ...
- MAT之prim算法
prim算法 边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1 ...
- HDU 4832 Chess(DP+组合数学)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,“王”在棋盘上的走法遵循十字路 ...
- (转载)R14也称作子程序连接寄存器
R14也称作子程序连接寄存器(Subroutine Link Register)或连接寄存器LR.当执行BL子程序调用指令时,R14中得到R15(程序计数器PC)的备份. 其他情况下,R14用作通用寄 ...
- AJax 学习笔记二(onreadystatechange的作用)
AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...
- PAT乙级 1031. 查验身份证(15) 标志要清零!!!!!!!!!
1031. 查验身份证(15) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 一个合法的身份证号码由17位地区. ...
- c++ 容器(list学习总结)
list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据).一个前驱指针和一个后驱指针.它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内 ...