热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

C#实现控制线程池最大数并发线程

这篇文章主要介绍了C#实现控制线程池最大数并发线程的相关资料,需要的朋友可以参考下

1. 实验目的:

      使用线程池的时候,有时候需要考虑服务器的最大线程数目和程序最快执行所有业务逻辑的取舍。
并非逻辑线程越多也好,而且新的逻辑线程必须会在线程池的等待队列中等待 ,直到线程池中工作的线程执行完毕,
才会有系统线程取出等待队列中的逻辑线程,进行CPU运算。

2.  解决问题:

     如果不考虑服务器实际可支持的最大并行线程个数,程序不停往线程池申请新的逻辑线程,这个时候我们可以发现CPU的使用率会不断飙升,并且内存、网络带宽占用也会随着逻辑线程在CPU队列中堆积,而不断增大。

      如果我们想在主程序有200个http网络通讯需要执行,如何每次循环用10个线程并发处理10个网络http通讯回话,下一次循环只有在上一次循环的10个线程都执行完毕后才会执行下一次循环,并且主程序监听和等待200个http网络通讯都在CPU线程池中执行完毕后,才会退出主程序。

 3.  实现逻辑:

      我们通过两个AutoResetEvent和线程监听器Monitor,分别实现:

       wait_sync:   任务线程的 并发执行,每次循环只处理最大10个线程分别对网络做http通讯回话。并且当前循环的10个线程都执行完毕后,才会进行下一次循环处理。
       wait_main: 主程序线程的监听和等待,只有所有任务线程都执行完毕后,主程序线程才会退出程序。
       list_Thread: 负责记录每次循环,CPU实际分配的系统线程的个数。和Monitor配合使用,Monitor.Enter(list_Thread)=占用共享线程资源的占用锁,Monitor.Exit(list_Thread)释放共享线程资源的占用锁。  
       n_total_thread: 配合wait_main使用,记录全部逻辑线程,已经执行完毕的当前总个数,用来判断主线程是否还需要继续等待,还是可以结束主程序运行。

4. 主要代码:

    线程池控制代码,如下:

/// 
/// 多线程调用WCF
/// 
/// 调用WCF的方式,1=Restful,2=Tcp
/// 
static void DoTest_MultiThread(string select, long num)
{
  int n_max_thread = 10; // 设置并行最大为10个线程
  int n_total_thread = 0; // 用来控制:主程序的结束执行,当所有任务线程执行完毕
 
  ILog log_add = new LogHelper("Add_Thread");
  ILog log_del = new LogHelper("Del_Thread");
  ILog log_wait = new LogHelper("Wait_Thread");
  ILog log_set = new LogHelper("Set_Thread");
  ILog log_for = new LogHelper("For_Thread");
 
  Console.Title = string.Format("调用WCF的方式 => {0}, 调用次数=> {1}"
    , select == "1" ? "Restful" : "Socket"
    , num);
   
  List list_Thread = new List();
 
  System.Threading.AutoResetEvent wait_sync = new System.Threading.AutoResetEvent(false); // 用来控制:并发最大个数线程=n_max_thread
  System.Threading.AutoResetEvent wait_main = new System.Threading.AutoResetEvent(false); // 用来控制:主程序的结束执行,当所有任务线程执行完毕
 
  DateTime date_step = DateTime.Now;
  for (long i = 0; i 0 && (i+1-1) % n_max_thread == 0) // -1 表示第max个线程尚未开始
    {
      //log_wait.Info(string.Format("thread n= {0},for i= {1}", dic_Thread.Count, i + 1));
      wait_sync.WaitOne(); // 每次并发10个线程,等待处理完毕后,在发送下一次并发线程
    }
    log_for.Info(string.Format("thread n= {0},for i= {1}", list_Thread.Count, i + 1));
 
    System.Threading.ThreadPool.QueueUserWorkItem
      ((data) =>
      {
        int id = System.Threading.Thread.CurrentThread.ManagedThreadId;
        System.Threading.Monitor.Enter(list_Thread);
        list_Thread.Add(id);
        System.Threading.Monitor.Exit(list_Thread);
 
        log_add.Info(string.Format("id={0}, count={1}", id, list_Thread.Count)); // 日志
 
        if (select == "1") // Restful方式调用
        {
          Query_Htty();
        }
        else
        {
          Query_Socket();
        }
 
        n_total_thread += 1;
        if (list_Thread.Count == (n_max_thread) || n_total_thread == num)
        {
          list_Thread.Clear();
          //log_set.Info(string.Format("thread n= {0},for i= {1}", dic_Thread.Count, i + 1));
          //wait_sync.Set(); 
          if (n_total_thread != num)
          {
            wait_sync.Set(); // 任务线程,继续执行
          }
          else
          {
            wait_main.Set(); // 主程序线程,继续执行
          }
        }
      }, list_Thread);
  }
 
  wait_main.WaitOne();
 
  Console.WriteLine(string.Format("总测试{0}次,总耗时{1}, 平均耗时{2}"
    , num
    , (DateTime.Now - date_step).ToString()
    , (DateTime.Now - date_step).TotalMilliseconds / num));
 
  Query_Thread();
}

  WCF后台服务代码

private static ILog log = new LogHelper("SeqService"); // 日志
private static Dictionary dic_thread = new Dictionary(); // 线程列表
 
private static long Num = 0; // 线程个数
private static object lock_Num = 0; // 共享数据-锁
 
/// 
/// 在线申请流水号
/// 
/// 
[WebGet(UriTemplate = "GetSeqNum/Json", RespOnseFormat= WebMessageFormat.Json)]
public string GetSeqNumber()
{ 
  lock (lock_Num)
  {
    Num++;
    int id_thread = System.Threading.Thread.CurrentThread.ManagedThreadId;
    DateTime now = DateTime.Now;
    if (!dic_thread.TryGetValue(id_thread, out now))
    {
      dic_thread.Add(id_thread, DateTime.Now);
    }
 
  }
  string ret = DateTime.Now.ToString("yyyyMMdd") + Num.ToString(new string('0', 9)); 
 
  log.Info(string.Format("{0}, Thread={1}/{2}", ret, System.Threading.Thread.CurrentThread.ManagedThreadId, dic_thread.Count));
  return ret;
}
   

5.  实验结果

1. 10000个WCF网络http请求,CPU分成每次10个(10可以按需求调整)线程并发执行,并且主程序在所有请求都执行完毕后,才退出主程序。

1. 前端日志:LogFile\Add_Thread\Info

2. WCF日志:LogFile\SeqService\Info


推荐阅读
  • REST API 时代落幕,GraphQL 持续引领未来
    尽管REST API已广泛使用多年,但在深入了解GraphQL及其解决的核心问题后,我深感其将引领未来的API设计趋势。GraphQL不仅提高了数据查询的效率,还增强了灵活性和性能,有望成为API开发的新标准。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文深入探讨了ASP.NET Web API与RESTful架构的设计与实现。ASP.NET Web API 是一个强大的框架,能够简化HTTP服务的开发,使其能够广泛支持各种客户端设备。通过详细分析其核心原理和最佳实践,本文为开发者提供了构建高效、可扩展且易于维护的Web服务的指导。此外,还讨论了如何利用RESTful原则优化API设计,确保系统的灵活性和互操作性。 ... [详细]
  • 谈起RESTFUL大家未免都耳熟能详,但是要介绍一下它是什么,可能就是停留在听过或者见过的阶段了。一贯喜欢以通俗的语言来消化知识的小马自然不会放过它了& ... [详细]
  • 摘要:本文中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务在读者正在工作的 ... [详细]
  • 1.研究背景及其意义互联网从发展到至今,已经深入到人们的日常生活中,并且不论老人还是小孩,多少都会接触到互联网。在这个越来越信息化的社会& ... [详细]
  • RocketMQ在秒杀时的应用
    目录一、RocketMQ是什么二、broker和nameserver2.1Broker2.2NameServer三、MQ在秒杀场景下的应用3.1利用MQ进行异步操作3. ... [详细]
  • 本文最初发表在Thorben Janssen的Java EE博客上,每周都会分享最新的Java新闻和动态。 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 性能测试中的关键监控指标与深入分析
    在软件性能测试中,关键监控指标的选取至关重要。主要目的包括:1. 评估系统的当前性能,确保其符合预期的性能标准;2. 发现软件性能瓶颈,定位潜在问题;3. 优化系统性能,提高用户体验。通过综合分析这些指标,可以全面了解系统的运行状态,为后续的性能改进提供科学依据。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • DingoAPI中的转化器(Transformer)有点类似Laravel框架自带的API资源类,都是用于对返回的响应数据进行格式化,通过转化器,你可以轻松实现将对象转化为数组,并支持整型和布尔类型之间的转化,以及分页结果和嵌套关联。这篇教程我们主要讨论转化器在DingoAPI中的使用,这里的转化器包括以下两层意思:在介绍Dingo转化器使用之前,有必要大致了解下其底层实现原理。 ... [详细]
  • 记录工作和学习中遇到和使用过的Python库。Target四个Level整理Collect学习Learn练习Practice掌握Master1.Python原生和功能增强1.1py ... [详细]
author-avatar
全拼wangziyiva_632
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有