最近在研究高並發下,如何准確測得方法執行時間,我想到的辦法是這樣的:可以這樣比喻3000名運動員再跑馬拉松,起點還不同,突然跑道上到了一棵樹,這棵樹又恰好能攔住所有人,待所有人都跑到這顆樹前的時候,樹就挪開了,而此時運動員之間的距離就是最小的。
而我運用lock機制,達到這種效果,只可惜lock似乎對阻塞線程的隊列有一定限制,隊列滿了就一定要放出一個,否則就會報出異常,而且隊列大小似乎是2000~3000線程來着的。
代碼如下:
using System; using System.Collections.Generic; using System.Threading; namespace Test { //測試並發時間委托 public delegate void ConcurrencyTest(); /// <summary> /// 高並發測試類 /// </summary> public static class HighConcurrencyTest { /// <summary> /// 測試高並發下單個委托的執行時間 /// </summary> /// <param name="count">並發計數</param> /// <param name="cTest">委托</param> /// <param name="sizeThread">一個線程執行的估計時間,可以估計的大些,默認是6毫秒</param> /// <returns></returns> public static double StartTest(int count,ConcurrencyTest cTest,int sizeThread=6) { #region 為保證之后取得的時間准確度,初始化 ConcurrentLock cLock = new ConcurrentLock(); ConcurrentLock autoLock = new ConcurrentLock(); GC.Collect(); GC.Collect(); GC.Collect(); GC.Collect(); #endregion #region 測算1億次if時間,並按比例計算出時間差 int max = ((count + 1) * count) / 2;//if被操作的總次數 double stime = new TimeSpan(DateTime.Now.Ticks).TotalMilliseconds; for (int i = 0; i < 100000000; i++) { if (cLock.EndTime == -1) { } } double etime = new TimeSpan(DateTime.Now.Ticks).TotalMilliseconds; double ifSpan = ((etime - stime) / 100000000d) * max; #endregion #region 清理內存使用,再初始化 GC.Collect(); GC.Collect(); GC.Collect(); GC.Collect(); Thread.Sleep(3000); #endregion #region 執行,執行原理如下,因為線程開啟的時間,各個線程之間存在時間差,現在采取一種辦法,使其時間差只是一個if判斷 List<Thread> threads = new List<Thread>(); int current = 0; for (int i = 0; i < count; i++) { var thread = new Thread(() => { //開始,擋路所有線程 lock (autoLock) { if (autoLock.StartTime == -1) { autoLock.StartTime = new TimeSpan(DateTime.Now.Ticks).TotalMilliseconds; Thread.Sleep(sizeThread * count); } } //釋放擋路的路牌 #region 委托執行 cTest(); #endregion //結束使用原子計數器 Interlocked.Increment(ref current); if (current >= count) { //此時所有線程都運行完該委托 autoLock.EndTime = new TimeSpan(DateTime.Now.Ticks).TotalMilliseconds; } }); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.MTA); threads.Add(thread); } foreach (var t in threads) { t.Start(); } foreach (var t in threads) { t.Join(); } #endregion return (double)(autoLock.EndTime - autoLock.StartTime - sizeThread * count - ifSpan) / (double)count; } } class ConcurrentLock { public double StartTime { get; set; } public double EndTime { get; set; } public ConcurrentLock() { StartTime = -1; EndTime = -1; } public void Reset() { StartTime = -1; EndTime = -1; } } }