在C#中,系统提供了GUID类,用户可以通过该类来获得128位的唯一标识,但是该标识不具有可读性,很难把该GUID显示在界面上,以当前时间精确到毫秒来作为GUID是一个比较不错的做法,但是DateTime.now的误差是100ms左右,无法在毫秒级的并发情况下获得不同的时间。

  在项目中,为了在界面上面显示时间相关的单号,是使用Datetime.now.ToString("yyyyMMddHHmmssfff"),结果在毫秒级多次调用该函数的时候,发现获得的字符串居然是一样的。在晚上查了一下,DateTime.now是有误差的,误差是100ms左右。没有很好的获得毫秒级时间的方法,我的想法是在该字符串后面加上个标识来使该字符串变得“唯一”。每次调用该方法时,该标识+1。去掉年份的4位,在后面加上该标识,从而保持获得的id依旧是17位。当该标识==9999时,将其重置为0。这样就可以获得一个唯一的时间相关的字符串了。类似这样:

  

datetime.now.ToString()+(flag++) .ToString();

if (flag >= ) flag = ;

  在并发的情况下,需要使+(flag++)原子化,如下:

static int flag = ;
static object o = new object();
public static string GetTimeGuid(){
int pFlag = ;
Monitor.Enter(o);
if (flag++>=9999) flag = ;
pFlag = flag;
Monitor.Exit(o);
return DateTime.Now.ToString("MMddHHmmssfff")+pFlag.ToString();
}

  值得注意的是,返回的字符串中是访问的局部变量pFlag而不是flag,因为此时已经不在Monitor里面了,无法保证flag是否只执行过一次++操作。我没有在此处使用interlock中的方法,是因为无法做到既flag++且读取flag的值并判断flag是否大于9999这三步操作的整体的原子性,只能使用锁。开始我担心锁会造成过多的性能损耗,因此对该方法进行了测试,

static void Main(string[] args)
{
var array = new string[];
var taskArray = new Task[];
var stopwatch = new Stopwatch();
for (var i = ; i < ; i++)
{
var p = i;
Action ac = () => array[p] = GetTimeGuid();
taskArray[p] = new Task(ac);
}
stopwatch.Start();
foreach (var t in taskArray)
{
t.Start();
}
var factory = new TaskFactory();
factory.ContinueWhenAll(taskArray, t => {
stopwatch.Stop();
long time1, time2;
time1 = stopwatch.ElapsedMilliseconds;
foreach (var item in array)
{
Console.WriteLine(item);
}
for (var i = ; i < ; i++)
{
var p = i;
Action ac = () => array[p] = DateTime.Now.ToString("yyyyMMddHHmmssfff");
taskArray[p] = new Task(ac);
}
stopwatch = new Stopwatch();
stopwatch.Start();
foreach (var task in taskArray)
{
task.Start();
}
factory.ContinueWhenAll(taskArray, n =>
{
stopwatch.Stop();
time2 = stopwatch.ElapsedMilliseconds;
foreach (var item in array)
{
Console.WriteLine(item);
}
Console.WriteLine($"{time1},{time2}");
});
}); Console.Read();
}

这段代码我在我的老旧笔记本上面和台式机上面跑,结果相差非常大,台式机上面只差5ms以内,但是在笔记本上面要差10倍以上。

本文介绍了一种将时间作为GUID的方法,欢迎在评论区和我讨论。

最新文章

  1. Hammer.js分析(一)——基础结构
  2. 大一上学期的一点小疑惑,代码验证ok
  3. 1.Mybatis原理
  4. Android 动画之TranslateAnimation应用详解
  5. JS后退, JS返回上一页, JS返回下一页
  6. H5页面音频自动播放问题
  7. android如何保存读取读取文件文件保存到SDcard
  8. BZOJ 1037 [ZJOI2008]生日聚会Party(单调DP)
  9. IT忍者神龟之Struts2.xml配置全然正确流程能走通可是有红叉解决
  10. NDK常见错误
  11. linux 卸载安装node npm
  12. 5分钟了解TypeScript
  13. java.lang.OutOfMemoryError: PermGen space (jvm内存泄漏解决办法)
  14. 【BZOJ5292】[BJOI2018]治疗之雨(高斯消元)
  15. Dockerfile命令大全
  16. JVM总结(六):晚期(运行期)优化
  17. Nginx 如何设置反向代理
  18. MySQL主从复制半同步复制原理及搭建
  19. GD32芯片移植完全攻略
  20. Review——JS的异步与同步

热门文章

  1. [Codeforce526F]:Pudding Monsters(分治)
  2. pymysql 处理数据的几种方式
  3. 冲刺周三The Third Day
  4. php 判断字符串包含
  5. ACE官网
  6. React Native商城项目实战05 - 设置首页的导航条
  7. tensorflow源码分析——LSTMCell
  8. oracle备份和还原
  9. 【flask_sqlalchemy】模糊查询
  10. 【1】mongoDB 的安装及启动