zoukankan      html  css  js  c++  java
  • 深入浅出多线程系列之三:线程池

    线程池:

    每一个线程默认会被分配1MB的内存,在C#中,这些都是实打实的分配的,当一个线程启动的时候,为了分配临时堆栈大约需要花费几百微秒的时间。

    线程池通过循环利用线程可以让你更高效的利用线程。

     

    线程池就像外包的劳务队一样,有任务给他们,他们会管理劳务工的一切,你不需要去花时间去找单个劳务工,然后完成任务就解雇她,

    对劳务队而言,劳务工完成了你的这个任务,还是会回到自己的团队中的,劳务工的管理也不需要你去负责,因为这由劳务队处理了,

    如果任务太多了,劳务队会自己招一个劳务工,如果还不够就继续招,但是如果任务比较少,而劳务工又比较多的话,对不起,劳务队的管理人员就会解雇一部分劳务工了。

     

    有很多方法可以进入线程池:

    1. 借助Task Parallel Library(framework 4.0)
    2. 调用ThreadPool.QueueUserWorkItem
    3. 借助异步委托。
    4. 借助BackgroundWorker. 

    下面的一些构造间接的使用了线程池:

    1. WCF,Remoting,Asp.net, asmx web services应用程序。
    2. System.Timers.Timer System.Threading.Timer.
    3. framework的一些异步方法,例如WebClient 类,和大部分BeginXXX方法。
    4. PLINQ 

    使用线程池的一些问题:

    1. 不可以设置一个线程池线程的名字。
    2. 线程池线程全部都是后台线程。
    3. 阻塞一个线程池线程可能会触发创建一个新线程,除非你调用ThreadPool.SetMinThreads方法。

      

    通过Thread.CurrentThread.IsThreadPoolThread属性可以查询一个线程是否是线程池线程。

     

    实战ThreadPool

    1:通过Task使用线程池:

            public static void MainThread()
            {
                Task
    <string> task = Task.Factory.StartNew<string>
                    (() 
    => DownloadString("http://www.google.com"));

                
    //DoSomething
                string result = task.Result;
            }

            
    static string DownloadString(string uri)
            {
                
    using (var wc = new System.Net.WebClient())
                    
    return wc.DownloadString(uri);
            }

     当查询task.Result的时候线程阻塞,等待task返回Result。

     

    2:通过ThreadPool.QueueUserWorkItem

            public static void MainThread()
            {
                ThreadPool.QueueUserWorkItem(Go);
                ThreadPool.QueueUserWorkItem(Go, 
    123);
                
                Console.ReadLine();
            }

            
    static void Go(object data)
            {
                Console.WriteLine(
    "Hello from the thread pool! " + data);
            }

    Output:

    Hello from the thread pool!

    Hello from the thread pool! 123

     

    3:借助委托的BeginXXX方法:

            public static void MainThread()
            {
                Func
    <stringint> method = Work;
                method.BeginInvoke(
    "test", Done, method);
            }

            
    static int Work(string s) { return s.Length; }

            
    static void Done(IAsyncResult cookie)
            {
                var target 
    = (Func<stringint>)cookie.AsyncState;
                
    int result = target.EndInvoke(cookie);
                Console.WriteLine(
    "String length is:" + result);
            }

    在这里将method当作参数进行传递后,在cookie的AsyncState中就可以使用传递的method了,

    因为cookie.AsyncState类型是object,所以需要进行转换,然后调用EndInvoke方法来获取结果。

     

    参考资料:

    http://www.albahari.com/threading/

    CLR Via C# 3.0

  • 相关阅读:
    [WinAPI] API 13 [遍历指定目录 打印文件和其他属性]
    2014-3-12 星期三 小雨 [及时完成不堆积]
    2014-3-11 星期二 晴 [卓有成效 master 摸索计划方案]
    [ACM_几何] UVA 11300 Spreading the Wealth [分金币 左右给 最终相等 方程组 中位数]
    [ACM_水题] UVA 11729 Commando War [不可同时交代任务 可同时执行 最短完成全部时间 贪心]
    [ACM_水题] UVA 11292 Dragon of Loowater [勇士斗恶龙 双数组排序 贪心]
    [WinAPI] API 12 [获取程序所在的目录、程序模块路径,获取和设置当前目录]
    [WinAPI] API 11 [创建目录]
    [WinAPI] API 10 [创建、打开、读写文件,获取文件大小]
    java解析json数组
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2052561.html
Copyright © 2011-2022 走看看