使用DateTime.Now.Ticks生成唯一的数字id

本文关键字:唯一 数字 id DateTime Now Ticks 使用 | 更新日期: 2023-09-27 18:09:46

我需要生成一个唯一的数字ID来附加到传入请求。此ID仅临时用于跟踪请求,并在请求完成处理后丢弃。此ID将仅在此应用程序的上下文中使用,但需要以高性能多线程方式分配。

我正在考虑使用DateTime.Now.Ticks为这个ID,但想知道DateTime.Now.Ticks是否仍然可以生成一个冲突的ID,如果同时的请求正在并发处理?

如果有人能建议一个更好的方法来生成这些id(最好是一个不是Int64像Tick是)在多线程环境中,请让我知道。如果在递增之前不需要锁定数字,那么像递增数字这样简单的东西就足够了。

使用DateTime.Now.Ticks生成唯一的数字id

您只需要使用一个静态变量,每次需要另一个惟一值时该变量递增。你可以通过使用Interlocked使这个线程安全并且仍然非常快。增量方法…

// Declaration
private static int safeInstanceCount = 0;
// Usage
{
      ...
      Interlocked.Increment(ref safeInstanceCount);
      ...
}

DateTime.Now对于这个目的来说绝对是糟糕的。你最多只能得到1毫秒的分辨率;在最坏的情况下,NT为17毫秒,CE/Compact Framework为1秒(!)。

考虑使用Interlocked.Increment方法作为快速的、线程安全的计数器。

以每个线程ID开始(如果多个线程发起请求),并与每个线程计数器连接(如果每个线程期望发起多个请求)。

获取一个强随机数或使用GUID

  • http://www.codeproject.com/KB/security/CryptoPasswordGenerator.aspx
  • http://msdn.microsoft.com/en-us/library/system.random.aspx
  • http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

如果高性能是必须具备的特性,则按单调顺序分配序号。通过为每个处理消息的线程"保留"一定范围的ID(比如,20-100)来防止锁争用。这样,您只需在20-100次迭代中锁定序列生成器一次。

如果你知道你要有多少线程(或至少一个上限),你可以划分你的ID空间之间的线程,计算ID作为一个(线程本地)计数器的值和线程的ID -例如,counter_value++ << 8 | thread_id。因此,不需要线程之间的协调或锁定,并且生成ID只需要一个增量、一个位移和一个或。

如果你使用系统线程ID,你的ID会稍微长一些,但是你不需要手动为你的线程分配ID

可以使用此属性,但要支付1ms,这并不重要!

public static long UniqId { 
    get { 
        Thread.Sleep(1); 
        return long.Parse(DateTime.Now.ToString("yyMMddHHmmssffff")); 
    } 
}

我正在使用基于时间的简单代Id,它可能会有所帮助。

private static readonly string prefixNumber = ConfigManager.Current.GetAppSetting("AppTimeIdPrefix", "");
private static readonly DateTime epoch = DateTime.SpecifyKind(DateTime.Parse(ConfigManager.Current.GetAppSetting("AppTimeIdEpoch", "1970/01/01")), DateTimeKind.Utc);
/// <summary>
/// DateTime.Now is only updated every 10-15ms.
/// </summary>
private static long lastTime = CurrentTimeMilliseconds();
private static readonly object timeLock = new object();
private static long CurrentTimeMilliseconds()
{
   return (long)(DateTime.UtcNow.ToUniversalTime() - epoch).TotalMilliseconds;
}
public static long CreateId()
{
    lock (timeLock)
    { // prevent concurrent access to ensure uniqueness
        long original, newValue;
       do
      {
         original = lastTime;
         newValue = Math.Max(CurrentTimeMilliseconds(), original + 1);
      } while (Interlocked.CompareExchange(ref lastTime, newValue, original) != original);
        return long.Parse(string.Format("{0}{1}", prefixNumber, newValue));
     }
}

参考如何确保时间戳总是唯一的?