使用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是)在多线程环境中,请让我知道。如果在递增之前不需要锁定数字,那么像递增数字这样简单的东西就足够了。
您只需要使用一个静态变量,每次需要另一个惟一值时该变量递增。你可以通过使用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));
}
}
参考如何确保时间戳总是唯一的?