在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的方法,欢迎在评论区和我讨论。

以当前时间作为GUID的方法的更多相关文章

  1. 无锁版以时间为GUID的方法

    之前的博客 将时间作为GUID的方法 中,我使用了锁.我在实际的使用中,错将锁的释放放在了if语句中,这纯粹是我的失误,导致了很严重的错误.因此我在想是否有无锁的将时间作为GUID的方式,答案是使用I ...

  2. Windows与Linux/Mac系统时间不一致的解决方法

    Windows与Linux/Mac系统时间不一致的解决方法 分类: linux2012-02-12 14:25 1691人阅读 评论(1) 收藏 举报 windowsubuntusystemlinux ...

  3. python_way day18 html-day4, Django路由,(正则匹配页码,包含自开发分页功能), 模板, Model(jDango-ORM) : SQLite,数据库时间字段插入的方法

    python_way day18 html-day4 1.Django-路由系统   - 自开发分页功能 2.模板语言:之母板的使用 3.SQLite:model(jDango-ORM) 数据库时间字 ...

  4. PHP获取时间日期的多种方法

    分享下PHP获取时间日期的多种方法. <?php echo "今天:".date("Y-m-d")."<br>";     ...

  5. IOS--UIDatePicker 时间选择器 的使用方法详细

    IOS--UIDatePicker 时间选择器 的使用方法详细 // 主要有下面四种类型:   // 日期显示. // 日期和时间显示. // 时间显示. // 倒计时选择       // UIDa ...

  6. Python中日期和时间格式化输出的方法

    本文转自:https://www.jb51.net/article/62518.htm 本文实例总结了python中日期和时间格式化输出的方法.分享给大家供大家参考.具体分析如下: python格式化 ...

  7. JavaScript生成GUID的方法

    一.生成GUID的方法一     JScript 代码   复制 function guid() { function S4() { return (((1+Math.random())*0x1000 ...

  8. CentOS集群自动同步时间的一种方法

    CentOS集群自动同步时间的一种方法 之前有篇日志是手动同步时间的 http://www.ahlinux.com/os/201304/202456.html 之所以这么干,是因为我们实验室的局域网只 ...

  9. [Swift通天遁地]五、高级扩展-(3)日期和时间类型的扩展方法

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

随机推荐

  1. JMS学习十(ActiveMQ支持的传输协议)

    ActiveMQ提供了一种连接机制,这种连接机制使用传输连接器(TransportConnector)实现客户端与代理(client - to - broker)之间的通信. 网络连接器(networ ...

  2. wannafly 挑战赛9 B 数一数(kmp)

    链接:https://www.nowcoder.com/acm/contest/71/B 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64b ...

  3. Java equals 和 hashCode 的这几个问题可以说明白吗?

    前言 上一篇文章 如何妙用 Spring 数据绑定? ,灵魂追问 环节留下了一个有关 equals 和 hashcode 问题 .基础面试经常会碰到与之相关的问题,这不是一个复杂的问题,但很多朋友都苦 ...

  4. spring boot: Whitelabel Error Page的解决方案

    http://blog.csdn.net/u014788227/article/details/53670112

  5. mysql中查看ef或efcore生成的sql语句

    http://www.solves.com.cn/it/sjk/MYSQL/2019-07-01/1336.html 涉及命令 1.开启general log模式 MySQL>set globa ...

  6. C/C++题库

    1.下面的代码输出什么?为什么? void foo(void) { unsigned int a = 6; int b = -20; (a+b > 6)?puts(“>6”):puts(“ ...

  7. mysql数据库修改一行数据格式不成功问题

    举个例子: mysql数据库中有两个字段publication_time.storage_time,我尝试着一个一个的修改字段的状态 #alter table books modify column ...

  8. python - MySQLdb 事务处理及批量执行executemany

    MySQL数据库有一个自动提交事务的概念,autocommit.含义是,如果开启autocommit, 则每一个语句执行后会自动提交.即一个语句视为一个事务. 在python使用的MySQLdb中,默 ...

  9. ES6数值的拓展

    二进制和八进制表示法 ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示. 如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法 Number(' ...

  10. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_6 Mybatis中使用Dao实现类的执行过程分析-增删改方法

    从测试类入手,断点调试 找到实现类,进入到insert方法里面 这里是SqlSession的接口里面的方法. 我们需要找SqlSession的实现类. DefaultSqlSession 里面有两个i ...