ThreadStatic应用(Identity补完)
关于Identity
起初做这个东西,是在一个内部组件中,用于在高并发的环境下得到一个较短的“相对”不重复标识字符串;(这里说的相对是指一定的数量下不重复)
灵感自然是来自于SqlServer的自增列和@@Identity变量
困扰
但是自从做完之后就有一个问题困扰这我,就是这个Current属性,这个属性的实用性其实非常的差
因为在高并发的环境中,使用Next()之后,即使立即使用Current属性得到的也是一个新的值,这点来说跟SqlServer的@@Identity是完全不同的
@@Identity的值无论并发多严重,你在同一个语句,或者说同一次会话中是不会改变的,除非该次会话新增了记录
(最近用了Oracle的序列对象,其中的sequence.CurrVal和@@Identity是一样的)
由于一直没有好的解决方案,而且没有这个功能不会影响这个类的使用,由于本身简单不需要维护,所以就渐渐遗忘了。
发现
昨日无意间发现了ThreadStaticAttribute这个特性,MSDN官方文档对其的描述是:
用 ThreadStaticAttribute 标记的 static 字段不在线程之间共享。 每个执行线程都有单独的字段实例,并且独立地设置及获取该字段的值。 如果在不同的线程中访问该字段,则该字段将包含不同的值。
看了说明之后,我立即想起了这个被遗忘在角落的对象。逐动手改造
修改代码
using System; namespace blqw
{
/// <summary> 自增序列,最大0xFFFFFFF,超过0xFFFFFFF回归1
/// </summary>
public static class Identity
{
[ThreadStatic]
static int? _ThreadCurrentId; static int _StaticId = ;
/// <summary> 当前值
/// </summary>
public static int Current
{
get { return _ThreadCurrentId.GetValueOrDefault(-); }
}
/// <summary> 当前值的String形式
/// </summary>
public static string CurrentString
{
get
{
if (_ThreadCurrentId.HasValue)
{
return GetString(_ThreadCurrentId.Value);
}
else
{
return null;
}
}
}
/// <summary> 获取一个id,每获取一次就会自增1,该方法在所有线程都是安全的
/// </summary>
public static int Next()
{
int i = System.Threading.Interlocked.Increment(ref _StaticId);
_ThreadCurrentId = i;
if (i > (0xFFFFFFF))
{
i = i - 0xFFFFFFF;
System.Threading.Interlocked.Exchange(ref _StaticId, i);
}
return i;
} //字符字典
static char[] _CharMap = new[]
{
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
}; /// <summary> 获取一个id的String表示形式,每获取一次就会自增1,该方法在所有线程都是安全的
/// </summary>
public static string NextString()
{
int number = Next();
return GetString(number);
} public static string GetString(int number)
{
if (number < )
{
throw new ArgumentOutOfRangeException("number", "number不能小于0");
}
int length = (int)Math.Log(number, ) + ;//52比较合理,不要改了
char[] c = new char[length];
for (int i = length - ; i > ; i--)
{
c[i] = _CharMap[number % ];
number = number / ;
}
c[] = _CharMap[number];
return new string(c);
}
}
}
测试
for (int i = ; i < ; i++)
{
new Thread(o =>
{
Console.WriteLine(o + " > Init: " + Identity.Current);
Thread.Sleep();
Console.WriteLine(o + " > Next: " + Identity.Next());
Thread.Sleep();
Console.WriteLine(o + " > Curr: " + Identity.Current);
Thread.Sleep();
Console.WriteLine(o + " > NStr: " + Identity.NextString());
Thread.Sleep();
Console.WriteLine(o + " > Curr: " + Identity.Current);
}).Start(i);
Thread.Sleep();
}
测试代码比较简单,开10个线程,让他们交错运行就行了
先上一个没有标记StaticThread的结果

把StaticThread注释掉运行,可以看到结果 在0号线程中使用Next得到值1 然后使用Current却得到2 ,因为在1号线程中调用Next影响了Current的值
这就是原来的效果,所以之前使用的时候都是 int i = Identity.Next() ;然后就拿 i 使用了
现在加在StaticThread

可以看到,现在线程0中的Current属性的值,并不会受到其他线程的影响了
总结
ThreadStatic特性允许我们将一个静态的变量的值在不同线程中是独立的
这个特性在某些情况下还是非常好用的
比如web应用中,每个请求都是一个独立的线程,如果我们希望将一个值作为静态字段全局使用,同时又不想影响其他用户,这时候一般我们是使用Session的
现在就可以有第二种选择了
Session可以将一个值长时间的保存,不于局限一次请求,但是Session需要应用System.Web.dll
ThreadStatic可以直接指定一个静态变量,但仅只能是当前请求,请求总段值就丢了
可以更新需要选择使用
最后,不知道ThreadStatic会不会带来额外的性能问题,希望知道的朋友可以告知
code
https://code.csdn.net/snippets/104950
ThreadStatic应用(Identity补完)的更多相关文章
- PHP函数补完:stream_context_create()模拟POST/GET
PHP函数补完:stream_context_create()模拟POST/GET PHP流的创建 在 2011年01月08日 那天写的 已经有 9408 次阅读了 感谢 参考或原文 服务 ...
- JavaScript函数补完:toString()
javascript中的toString()方法,主要用于Array.Boolean.Date.Error.Function.Number等对象.下面是这些方法的一些解析和简单应用,做个纪律,以作备忘 ...
- 展开隐形的翅膀,WPR003N补完篇
在上一回合要搞刷机!从它的尸体上踏过去!钢板云路由!WPR003N复活!成功启动OPENWRT中,笔者成功的让一个4年前主流芯片搭上OS的快船,留下一段佳话. 今天看着抽屉里的WPR003N,回忆它之 ...
- [TaskList] 省选前板子补完计划
省选前本子补完计划 [ ] 带权并查集 [ ] 树上莫队 - UOJ58 [WC2013]糖果公园 loj2485「CEOI2017」Chase
- bzoj Usaco补完计划(优先级 Gold>Silver>资格赛)
听说KPM初二暑假就补完了啊%%% 先刷Gold再刷Silver(因为目测没那么多时间刷Silver,方便以后TJ2333(雾 按AC数降序刷 ---------------------------- ...
- QBXT 2017GoKing problems 补完计划
10.11 Updata : 烦死了...麻烦死了...不补了..就这些吧 20171001 上: 100 + 90 + 90 = 280 = rank 8 T1 /* T1 从最大的数开始倒着枚举 ...
- NodeJS学习:爬虫小探补完计划
说明:本文在个人博客地址为edwardesire.com,欢迎前来品尝. 书接上回,我们需要修改程序以达到连续抓取40个页面的内容.也就是说我们需要输出每篇文章的标题.链接.第一条评论.评论用户和论坛 ...
- CodeVS1169 传纸条 [DP补完计划]
题目传送门 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...
- ACM模板(持续补完)
1.KMP #include<cstring> #include<algorithm> #include<cstdio> using namespace std; ...
随机推荐
- IOS 开发 ARC兼容MRC框架
在后面加 -fno-objc-arc
- POST 500 Internal Server Error
今天调试公司web后台时发现一个POST 500 Internal Server Error的错误. 本来VS本地调试没有发现这个问题,然后发布到服务器时才出现了.然后找了好久没找到什么原因,再仔细在 ...
- jQuery - 自定义伪类 [:pseudoclass]
有两种创建伪类的方法, 第一种, $.extend( $.expr[':'], { // 自定义的伪类名称:group group: function(element, index, matches, ...
- 我看见的第一个XCODE编译错误 - Command /applications.../clang failed with exit code 1
开始用XCODE学习Apple相关开发的东东,写些demo熟悉Object C,一直还没看见什么问题,昨晚在家把一些demo上传到代码服务器,今天在另外一台机器上下载下来编译,出现了问题: Preco ...
- "巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场
Combine String #include<cstdio> #include<cstring> #include<iostream> #include<a ...
- 基于VC的ACM音频编程接口压缩Wave音频(三)
(三)音 频 数 据 的 压 缩 下 面 说 明 使 用 CODEC 实 现 音 频 压 缩 的 过 程:假 设 源 信 号 为8K 采 样.16bits PCM 编 码. 单 声 道. 长 度 为1 ...
- sql 注入的防范(一)
为了保证程序的健壮性,我们必须对用户输入的数据做有效性验证,防止用户恶意提交数据. 关于防止 sql 注入 我主要从三个方面入手: 1.确认为正整数的,强制转化为int,$id =$_GET('id ...
- SAP DataServices企业定制培训
No. Item Remark 1 Dataservices overview DS概述 2 SAP Dataservices 安装与配置 DS的配置 3 DS ETL开发<1> for ...
- CAS 4.0.0RC 配置通过数据库认证用户登录
配置通过数据库认证用户登录 打开webapp\WEB-INF目录下的deployerConfigContext.xml,替换 <bean id="primaryAuthenticati ...
- 'sessionFactory' or 'hibernateTemplate' is required解决方法
这种情况就是在通过spring配置hibernate4的时候(注意,这里是hibernate4不是hibernate3,hibernate3的),使用的是HibernateDaoSupport的这种方 ...