當前位置:
首頁 > 知識 > 第46篇 多線程如何排隊執行

第46篇 多線程如何排隊執行

有一個這樣場景,程序會有一個非常耗時的操作,但要求耗時的操作完成後,再順序的執行一個不耗時的操作,而且這個程序的調用,可能存在同時調用的情況。

具體的模型如下:

第46篇 多線程如何排隊執行

從Start開始觸發了5個線程,經過一個longTimeJob同時執行,我們不關心longJob的執行時間和先後順序,根據Start的先後順序來執行一個ShortJob。下面我們用代碼來模擬上面的過程。

舉例說明:有ABCD 4個線程,進入的順序也是ABCD,A耗時3s,B耗時7s,C耗時1s,D耗時3s. 所以如果當4個線程都同時開始執行時,完成的先後順序為 CADB,但我們要求的順序是ABCD,也就是說C要等待AB執行完後,才能繼續後續的工作。

我們可以用請求bing搜索來模擬longTimeJob,根據傳入的序列來決定請求多少次,主要模擬方法如下:

private static async Task Test
{
var arry = new
{
10, 9, 8, 7, 6, 5, 4, 3, 2, 1
};
var listTask = new List>;
foreach (var i in arry)
{
var i1 = i;
var task = Task.Run( => DoJob(i1));

listTask.Add(task);
}

foreach (var task in listTask)
{
Console.WriteLine("輸出-->:" + await task);//
}
}

public static Task DoJob(int o)
{
return Task.Run( =>
{
DoLongTimeThing(o);
return o;
});
}

public static void DoLongTimeThing(int i)
{
Console.WriteLine("執行-->:" + i);
for (int j = 0; j < i; j++) { HttpGet("http://cn.bing.com/"); } Console.WriteLine("執行完畢-->:" + i);
}

public static string HttpGet(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";

HttpWebResponse response = (HttpWebResponse)request.GetResponse;
StreamReader reader = new StreamReader(response.GetResponseStream, Encoding.UTF8);
string content = reader.ReadToEnd;
return content;
}
catch (Exception e)
{
return e.Message;
}

}

執行結果:

第46篇 多線程如何排隊執行

上面的代碼大概能解決我們的問題,有一個問題,對於客戶的調用我們無法形成一個List,而且list是線程安全的,所以針對上述的方法在實際的業務場景中無法使用。

新思路

我們無法實現一個有序的Task列表,如果換一個角度考慮,當一個任務形成的時間,同時生成一個對應的HashCode,對HashCode進行一個隊列的入隊操作,當執行完成longTimeJob後,判斷是不是隊列的第一個Task的HashCode,如果是則執行,如果不是則繼續等待,切換線程。 具體如下思路如下圖:

第46篇 多線程如何排隊執行

public static Queue Queue = new Queue;
static void Main(string[] args)
{
var arry = new
{
10, 9, 8, 7, 6, 5, 4, 3, 2, 1
};

foreach (var i in arry)
{
Console.WriteLine("進入Job順序-->:" + i);
Test(i);
}
Console.ReadKey;
}

public static void Test(int i)
{
var taskId = Guid.NewGuid.ToString;
Queue.Enqueue(taskId);
Task.Factory.StartNew(DoJob, new object[] { i, taskId });
}
public static void DoJob(object o)
{
var oArry = (object[])o;
var n = (int)oArry[0];
var currId = oArry[1].ToString;

DoLongTimeThing(n);//

while (currId != Queue.Peek)
{
Thread.Sleep(1);//等線程切換
}

Console.WriteLine("DoShortJob輸出-->:" + n);//
//請求資料庫
Queue.Dequeue;
}
public static void DoLongTimeThing(int i)
{
Console.WriteLine("LongTimeJob執行-->:" + i);
for (int j = 0; j < i; j++) { HttpGet("http://cn.bing.com/"); } Console.WriteLine("LongTimeJob執行完畢-->:" + i);
}

public static string HttpGet(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";

HttpWebResponse response = (HttpWebResponse)request.GetResponse;
StreamReader reader = new StreamReader(response.GetResponseStream, Encoding.UTF8);
string content = reader.ReadToEnd;
return content;
}
catch (Exception e)
{
return e.Message;
}

}

運行結果如下:

第46篇 多線程如何排隊執行

雖然執行結果看起來很亂,但仔細比對可以發現最終的DoShortTime是按順序執行的。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

淺從System.Web.Http.Owin的HttpMessageHandlerAdapter看適配器模式
TP5 面向對象和命名空間
gdb常用命令及使用gdb調試多進程多線程程序
WindowManager.LayoutParams的探究

TAG:達人科技 |

您可能感興趣

線程撕裂者2990X跑分曝光 32核64線程無敵
蘋果A12性能殘暴 單線程5200分多線程13000分
AMD二代線程撕裂者8月13日發布:最多32核心64線程
C++11多線程 多線程傳參詳解
第405期:線程撕裂者渲染PC
AMD線程撕裂者二代擴軍:24核心48線程只要9999
疑似線程撕裂者三代跑分曝光 16核心32線程
線程撕裂者奪冠!2018年硬體排行榜:GTX1060最受歡迎
超線程成棄兒?九代酷睿9000系列規格令人鬱悶
新一代線程撕裂者曝光 32核64線程只是入門?
九代酷睿9000系列規格曝光:超線程成棄兒
撕裂者2990X現身:32核64線程
32核心64線程!AMD線程撕裂者二代旗艦2990X現身:加速4GHz
8核心16線程第九代酷睿i7 9700k,10nm?不一定
英特爾第十代U系列處理器曝光:i7-10710U為6核12線程
32核64線程!AMD新一代撕裂者8月13日起售
銳龍7 2800X現身,10核20線程
六核12線程 火影 地獄火X6促銷6699元
16核32線程銳龍R9-3950X已經很強 但AMD還有64核128線程的王牌
Exynos 9810跑分成績出爐:單線程破四千多核破萬