zoukankan      html  css  js  c++  java
  • 多线程和异步编程示例和实践-踩过的坑

    上两篇文章,主要介绍了Thread、ThreadPool和TPL

    多线程异步编程示例和实践-Thread和ThreadPool

    多线程异步编程示例和实践-Task

    本文中,分享两则我们在做多线程和异步编程中实际踩过的坑,实际生产环境遇到的问题,以及解决办法。

    1. HttpClient

    业务场景:使用HttpClient实现第三方业务推送,当第三方的Http服务器不通、或者返回很慢时

    • 线程数暴涨
    • Asp.NetAsp.Net MVC场景下,并发多线程导致的线程阻塞:HttpClient.PostAysnc/GetAsync.Result

    第一种线程数暴涨的问题,很容易理解,线程执行的慢,线程创建的速度快,一直在执行,导致线程不断创建线程、线程数不断暴涨。

    根本原因是HttpClient的超时时间配置的太长,这点存于业务设计的问题,理论上简单请求3s没响应就该超时了,复杂长时间请求使用异步任务(我们的消息应用中心)处理。

    第二种,Asp.Net或者Asp.Net MVC场景下,使用HttpClient,同时GetAsync.Result,异步变同步,这就会出现请求Hang住,线程死锁、请求没响应。

    根本原因Http异步请求的上下文的互相等待导致的。详细分析可以参考下面的link:

    http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

    有什么好的解决方案吗

    • HttpWebRequest代替HttpClient实现各类Http请求,这个类虽然是.net 2.0下的,但是功能的确很强大,应用一般的Http请求没啥问题!
    • 使用HttpWebRequest实现同步Get、Post请求,避免在Asp.Net场景下使用HttpClient.PostAsync/GetAsync.Result(异步变同步)带来的线程死锁,因为Asp.Net机制下Http异步请求的上下文的互相等待导致的。
    • 合理设置Http请求的超时时间,超时即返回,防止线程数暴涨
    • 对于第三方服务器的通信,建议在内存中维护一个联通性状态字典,每隔一段时间更新一次,如果不通,直接就不发起Http请求了,这个策略更像是设计上的优化,但是效果很好!

    上两个示例代码:

    如果非用HttpClient不可,也是有招的:

    很简单,从WebApi,或者Controller这一层全部异步化。前后全部异步。同时,

    设置:ConfigureAwait(false)

    2. Winform、Console或者Windows服务下,前台线程异常导致的进程退出

    这个问题是很头疼的,主要是在提供的服务容器运行的插件代码中,使用了Thread,默认是前台线程,未正确处理异常,线程异常后,导致主进程退出!!!

    业务场景:Windows 服务版本下的消息应用中心,个推使用New Thread推送消息,线程未处理异常,异常后导致Windows Service异常关闭!

    结果很头大,就是整个消息应用中心进程退出了,所有消息处理业务全部受影响!

    根本原因:通过New Thread方式创建的线程,系统默认都是前台线程(IsBack),前台线程异常如果未处理,会导致应用程序退出,即使注册了AppDomain.CurrentDomain.UnhandledException事件处理,应用程序依然会挂掉。

    解决方案:在线程内部合理处理异常:记日志、返回值处理,但是不能throw

    补充:这里引出了一个重要的知识点:前台线程和后台线程

    两者的区别就是:

    • 应用程序必须运行完所有的前台线程才可以退出;
    • 对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。

    那么,Thread、线程池的线程、Task都各自属于哪一类线程?

    使用Thread建立的线程默认情况下是前台线程,即线程属性IsBackground=false.

    属于托管线程池的线程(即其 IsThreadPoolThread 属性为 true 的线程)是后台线程

    Task都是后台线程:Task需要在其运行过程中至少有一个前台线程在跑,否则会直接退出.

    周国庆

    2017/6/16

  • 相关阅读:
    C++中智能指针的设计和使用
    [转]C++ 智能指针详解
    C++ const 常量和常指针
    深入理解C++中的mutable关键字
    C++ 静态常量
    BZOJ 1875: [SDOI2009]HH去散步
    BZOJ 1024: [SCOI2009]生日快乐
    BZOJ 1059: [ZJOI2007]矩阵游戏
    bzoj 1833: [ZJOI2010]count 数字计数
    LUOGU P2587 [ZJOI2008]泡泡堂
  • 原文地址:https://www.cnblogs.com/tianqing/p/7025759.html
Copyright © 2011-2022 走看看