国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

ThreadPool.QueueUserWorkItem的性能問題

2019-11-17 02:17:46
字體:
供稿:網(wǎng)友

ThreadPool.QueueUserWorkItem的性能問題

引用:http://blog.csdn.net/sq_zhuyi/article/details/6869661

在WEB開發(fā)中,為了減少頁面等待時(shí)間提高用戶體驗(yàn),我們往往會把一些浪費(fèi)時(shí)間的操作放到新線程中在后臺運(yùn)行。

簡單的實(shí)現(xiàn)代碼就是:

//代碼一new Thread(()=>{    //do something}).Start();
View Code

但是對于一個(gè)請求量大的網(wǎng)址這樣做是很不現(xiàn)實(shí)的——每一個(gè)操作都要開啟一個(gè)新線程,最終會因CPU不堪重負(fù)而使網(wǎng)站掛掉。

更好的做法是使用線程隊(duì)列。

對于線程隊(duì)列ThreadPool.QueueUserWorkItem很多人應(yīng)該都不陌生,下邊看微軟的解釋:

將方法排入隊(duì)列以便執(zhí)行,并指定包含該方法所用數(shù)據(jù)的對象。此方法在有線程池線程變得可用時(shí)執(zhí)行。

它的作用就是將一些操作放入當(dāng)前線程之外的另外一個(gè)線程中執(zhí)行,它的使用方法很簡單:

//代碼二ThreadPool.QueueUserWorkItem(stat => {    //do something}, null);
View Code

它相對代碼一的優(yōu)點(diǎn)是會利用已經(jīng)創(chuàng)建過的空閑的線程,如果沒有空閑就排隊(duì),而不會盲目的一直創(chuàng)建下去。

但是它并沒有擺脫“創(chuàng)建新線程”的問題:過多的線程會占用更多的資源。由此我們不難想到,我們?yōu)槭裁床蛔约焊銈€(gè)隊(duì)列,讓它們在同一個(gè)線程中逐個(gè)執(zhí)行?對此,我寫了個(gè)簡單的實(shí)現(xiàn)類:

 1         public class BackgroundTasks 2         { 3             PRivate class TaskEntity 4             { 5                 public TaskEntity(Action<object> func, object data) 6                 { 7                     this.Function = func; 8                     this.Data = data; 9                 }10                 public Action<object> Function;11                 public object Data;12             }13             static Queue<TaskEntity> list = new Queue<TaskEntity>();14 15             static BackgroundTasks()16             {17                 Thread th = new Thread(RunTask);18                 th.IsBackground = true;19                 th.Start();20             }21             static void RunTask()22             {23                 while (true)24                 {25                     if (list.Count == 0)26                     {27                         Thread.Sleep(1000);28                     }29                     else30                     {31                         TaskEntity entity;32                         lock (list)33                         {34                             entity = list.Dequeue();35                         }36                         try37                         {38                             entity.Function(entity.Data);39                         }40                         catch { }41                         Thread.Sleep(10);42                     }43                 }44             }45 46             public static void Add(Action<object> func, object data)47             {48                 lock (list)49                 {50                     list.Enqueue(new TaskEntity(func, data));51                 }52             }53 54         }
View Code

該類的使用很簡單:

BackgroundTasks.Add((obj)=>{  Console.WriteLine("這個(gè)任務(wù)的添加時(shí)間是:{0}", obj as DateTime);}, DateTime.Now);

還有一個(gè)“實(shí)例版”的,就是針對每個(gè)方法,分別創(chuàng)建一個(gè)任務(wù)隊(duì)列:

 1 public class BackgroundTasks01<T> 2 { 3     private Action<T> Function; 4  5     private Queue<T> list = new Queue<T>(); 6  7     public BackgroundTasks01(Action<T> func) 8     { 9         this.Function = func;10 11         Thread th = new Thread(RunTask);12         th.IsBackground = true;13         th.Start();14     }15     private void RunTask()16     {17         while (true)18         {19             if (list.Count == 0)20             {21                 Thread.Sleep(1000);22             }23             else24             {25                 T data;26                 lock (list)27                 {28                     data = list.Dequeue();29                 }30                 try31                 {32                     Function(data);33                 }34                 catch { }35                 Thread.Sleep(10);36             }37         }38     }39 40     public void Add(T data)41     {42         lock (list)43         {44             list.Enqueue(data);45         }46     }47 48 }
View Code

blog類:

class Blog{    private int _blogId = 0;    public int BlogId    {        get { return _blogId; }        set { _blogId = value; }    }    private string _blogName = "";    public string BlogName    {        get { return _blogName; }        set { _blogName = value; }    }}
View Code

調(diào)用示例:

//方法二:var bg = new BackgroundTasks01<Blog>((blog) =>{    Console.WriteLine("BlogName:{0},BlogId:{1}", blog.BlogName, blog.BlogId);});int i = 0;while (i++ < 100){    bg.Add(new Blog() { BlogId = i, BlogName = "Default" });}Console.ReadLine();bg.Add(new Blog() { BlogId = 1000, BlogName = "張三" });bg.Add(new Blog() { BlogId = 1001, BlogName = "李四" });
View Code

這個(gè)設(shè)計(jì)既解決了異步執(zhí)行,又解決了占用資源的問題。

但是世界上沒有完美的東西,代碼也是如此,由于隊(duì)列中的任務(wù)是單線程執(zhí)行,可能會導(dǎo)致某些任務(wù)在很長時(shí)間后才會被執(zhí)行到,或者重啟IIS導(dǎo)致很多任務(wù)還沒有被執(zhí)行就被丟棄。

無論怎么,這種設(shè)計(jì)還是適用于很多“一般情況”。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 四子王旗| 曲靖市| 南澳县| 镇安县| 夏津县| 怀化市| 永泰县| 唐河县| 如皋市| 临猗县| 常宁市| 嵊州市| 扶绥县| 开平市| 镇沅| 灵璧县| 醴陵市| 砚山县| 连平县| 延津县| 聂拉木县| 焦作市| 兰坪| 永泰县| 盈江县| 肇庆市| 广宗县| 江山市| 临高县| 汉阴县| 屏东市| 新巴尔虎右旗| 民权县| 焦作市| 洛浦县| 静乐县| 荣昌县| 明水县| 丘北县| 景谷| 封丘县|