zoukankan      html  css  js  c++  java
  • C# 线程第三线程池

    概述

    线程池有那些优点:

    1.在多线程中线程池可以减少我们创建线程,并合理的复用线程池中的线程。因为在线程池中有线程的线程处于等待分配任务状态。

    2.不必管理和维护生存周期短暂的线程,不用在创建时为其分配资源,在其执行完任务之后释放资源。

    3.线程池会根据当前系统特点对池内的线程进行优化处理。

    线程池的缺点:

    我们把任务交给线程池去完成后,无法控制线程的优先级,设置线程的一些名称等信息。[不过我们可以在放入线程池之前加一层来完善这些工作]

    线程池参数设置

    示例代码:

    int workerThreads, completionPortThreads;
    
    ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads);
    
    ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池根据需要创建的最少数量的辅助线程:{0}.线程池根据需要创建的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads);
    
    //设置线程池默认参数
    ThreadPool.SetMaxThreads(100, 100);
    ThreadPool.SetMinThreads(2, 2);
    
    ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads);
    
    ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池根据需要创建的最少数量的辅助线程:{0}.线程池根据需要创建的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads);
    
    ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("可用辅助线程的数目:{0}.可用异步 I/O 线程的数目:{1}", workerThreads, completionPortThreads);

    输出结果:

    1.CLR线程池最大数:1023。I/O线程池最大数:1000。

    2.线程池中最大数目和最少数量我们都可以修改。

    [msdn建议:不能将辅助线程的数目或 I/O 完成线程的数目设置为小于计算机的处理器数目。

    如果承载了公共语言运行时,例如由 Internet 信息服务 (IIS) 或 SQL Server 承载,主机可能会限制或禁止更改线程池大小。

    更改线程池中的最大线程数时需谨慎。 虽然这类更改可能对您的代码有益,但对您使用的代码库可能会有不利的影响。

    将线程池大小设置得太大可能导致性能问题。 如果同时执行的线程太多,任务切换开销就成为影响性能的一个主要因素。]

    线程池的使用

    线程池的常用方法:

    public static bool QueueUserWorkItem(WaitCallback callBack, object state);

    WaitCallback:表示线程池线程要执行的回调方法。

    [ComVisible(true)]
    public delegate void WaitCallback(object state);

    示例代码:

    ThreadPool.SetMaxThreads(12, 12);
    
    int workerThreads, completionPortThreads;
    
    ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads);
    
    ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池根据需要创建的最少数量的辅助线程:{0}.线程池根据需要创建的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads);
    
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    
    WaitCallback callback = index =>
    {
        Console.WriteLine(String.Format("{0}: Task {1} started", stopwatch.Elapsed, index));
        Thread.Sleep(10000);
        Console.WriteLine(String.Format("{0}: Task {1} finished", stopwatch.Elapsed, index));
    };
    
    for (int i = 0; i < 20; i++)
    {
        ThreadPool.QueueUserWorkItem(callback, i);
    }
    Console.Read();

    输出结果:

     1 00:00:00.0009109: Task 0 started
     2 00:00:00.0011152: Task 2 started
     3 00:00:00.0010331: Task 1 started
     4 00:00:00.0013977: Task 3 started
     5 00:00:01.0640656: Task 4 started
     6 00:00:01.5959091: Task 5 started
     7 00:00:02.1282115: Task 6 started
     8 00:00:02.6604640: Task 7 started
     9 00:00:03.1919942: Task 8 started
    10 00:00:03.7241812: Task 9 started
    11 00:00:04.2562930: Task 10 started
    12 00:00:04.7883300: Task 11 started
    13 00:00:10.0337174: Task 0 finished
    14 00:00:10.0337912: Task 2 finished
    15 00:00:10.0341861: Task 3 finished
    16 00:00:10.0343205: Task 13 started
    17 00:00:10.0342149: Task 12 started
    18 00:00:10.0345326: Task 1 finished
    19 00:00:10.0347520: Task 14 started
    20 00:00:10.9400517: Task 15 started
    21 00:00:11.0639205: Task 4 finished
    22 00:00:11.0643085: Task 16 started
    23 00:00:11.5960161: Task 5 finished
    24 00:00:11.5966256: Task 17 started
    25 00:00:12.1279212: Task 6 finished
    26 00:00:12.1294851: Task 18 started
    27 00:00:12.6609840: Task 7 finished
    28 00:00:12.6613285: Task 19 started
    29 00:00:13.1921462: Task 8 finished
    30 00:00:13.7240561: Task 9 finished
    31 00:00:14.2560682: Task 10 finished
    32 00:00:14.7880441: Task 11 finished
    33 00:00:20.0342193: Task 13 finished
    34 00:00:20.0354372: Task 14 finished
    35 00:00:20.0343117: Task 12 finished
    36 00:00:20.9402809: Task 15 finished
    37 00:00:21.0662233: Task 16 finished
    38 00:00:21.5983967: Task 17 finished
    39 00:00:22.1293673: Task 18 finished
    40 00:00:22.6623133: Task 19 finished
    View Code

    1:00秒共开启4个线程(为线程池中最少线程数:当达到线程池中创建线程最小线程时,线程池开始创建线程)。
    2:01到04秒之间平均1秒创建一个线程.线程池创建线程每秒不会超过2个。
    3:04秒时线程池中的线程数已达最大值,无法在创建新的线程。
    4:10秒时线程池中线程ID0-4已完成任务,线程池又开始重新创建线程(线程ID为:12-15)共4个。

    CLR线程池与IO线程池

    测试CLR线程池占满后,会不会影响IO线程池的正常使用?

    示例代码:

    ThreadPool.SetMaxThreads(5, 5);    
    ThreadPool.SetMinThreads(5, 5);
    
    int workerThreads, completionPortThreads;
    
    ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
    Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads);
    
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    
    Stopwatch watch = new Stopwatch();
    watch.Start();
    
    //IO线程池
    WebRequest request = HttpWebRequest.Create("http://www.taobao.com/");
    request.BeginGetResponse(ar =>
    {
        var response = request.EndGetResponse(ar);
        Console.WriteLine(watch.Elapsed + ": Response Get");
    }, null);
    
    
    //CLR线程池
    for (int i = 0; i < 10; i++)
    {
        ThreadPool.QueueUserWorkItem(index => 
        {
            Console.WriteLine(String.Format("{0}: Task {1} started", watch.Elapsed, index));
            waitHandle.WaitOne(); //阻塞线程池
        },i);
    }
    
    Console.Read();

    输出结果:

    1. 把CLR线程池最大线程数和IO线程池最大线程数都设置为:5.

    2.向CLR线程池中增加10个线程任务,并且阻塞线程池。最后输出结果中只打印出5个线程运行的信息。CLR线程池已达最大线程数,IO线程依然有回复数据。

    证明CLR线程池占满后不会影响到IO线程池的使用。

  • 相关阅读:
    netty的ChannelPipeline执行顺序对inBound和outBound执行器造成的影响
    【转载,并做少量修改整合】Java 双亲委派模型与应用:SPI(Service Provider Interface)
    JDK1.8 论ConcurrentHashMap是如何扩容的
    如何解决Vue.js里面noVNC的截图问题之后篇——用web虚拟终端作为替代功能
    hihocoder 1036 Trie图
    Codeforces#390
    Codeforces#386
    codeforces 743D Chloe and pleasant prizes
    codeforces 742E (二分图着色)
    洛谷 P1280 尼克的任务题解
  • 原文地址:https://www.cnblogs.com/caokai520/p/4308380.html
Copyright © 2011-2022 走看看