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


    说到多线程异步编程,总会说起Thread、ThreadPool、Task、TPL这一系列的技术。总结整理了一版编程示例和实践,分享给大家。

    先从Thread和ThreadPool说起:

    1. 创建并启动线程

    2. 暂停线程

    当前线程在执行Thread.Sleep方法时,会等待指定的时间(1000ms)
    此时,当前线程处于阻塞状态:WaitSleepJoin

    3. 线程合并

    Thread.Join操作会阻塞当前线程,等待子线程完成后再进行运行。

    当程序运行时,启动了一个耗时较长的线程打印数字,每次打印输出前需要等待1000ms,我们在主程序中调用ThreadJoin方法,内部调用了thread.Join,该方法允许程序等待thread执行完成。

    当thread线程执行完成后,主线程会继续执行,输出Thread Completed!

    4. 线程终止

    当主程序和单独的数字打印线程运行时,主程序等待6000ms后对thread线程调用了Abort方法。这给线程触发ThreadAbortException异常,导致线程被终止!

    这个操作非常危险,因为该操作可以在任何时间发生并可能彻底摧毁应用程序。(Windows服务,因为线程(前台线程)异常退出)

    5.线程传递参数

    6. 线程安全和Lock

    线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。线程安全情况下,不会出现数据不一致或者数据污染的问题。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据! 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

    lock 关键字通过获取指定对象的互斥锁,将语句块标记为临界区,执行语句然后释放该锁。

    lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。使用Lock,会导致整个应用程序串行化,降低程序的并发能力,影响性能。

    到底什么场景下要使用lock保证线程安全:该串行就串行,该并行就并行。

    7. 线程的异常捕获和处理

    在线程中执行异常处理。线程(甚至是后台线程)中的未处理异常
    通常会终止进程,因此,在线程内部使用try/catch代码块来捕获异常,
    不可能在线程之外通过try/catch捕获异常

    8. 线程池ThreadPool

    核心类:System.Threading.ThreadPool, 线程池受.Net CLR管理的,每一个CLR都有一个线程池实例。
    每个进程都有一个线程池。线程池的默认大小为:每个可用的处理器有 25 个线程。使用 SetMaxThreads 方法可以更改线程池中的线程数。每个线程使用默认的堆栈大小并按照默认的优先级运行。
    ThreadPool类型拥有一个QueueUserWorkItem的静态方法。该静态方法接收一个委托,代表用户自定义的一个异步操作。在改方法被调用后,委托会进入到内部队列中。如果线程池中没有任何线程,将创建一个新的工作者线程(worker thread)并将队列中的第一个委托放入到该工作者线程中。
    如果向线程池中放入新的操作,当之前的所有操作完成后,很可能只需重用一个线程来执行这些新的操作。如果QueueUserWorkItem执行的频率过快,线程池将创建更多的线程来执行这些新放入的异步委托。
    线程池中的线程数是有限的,如果没有空闲的线程来执行这些异步委托操作,这种情况下,新的异步委托操作将在线程池的内部队列中等待,直到线程池中年的工作者线程空闲(有能力)来执行。
    当停止向线程池中放入新的异步委托操作时,线程池会删除一定事件后过期的不在使用的线程,同时释放不再使用的系统资源。

     

    9. 不适合使用线程池的场景

    在以下几种情况下,适合于创建并管理自己的线程而不是使用线程池线程:
    •需要前台线程。
    •需要使线程具有特定的优先级。
    •任务会导致线程长时间被阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
    •需要将线程放入单线程单元。所有 ThreadPool 线程均处于多线程单元中。
    •需要具有与线程关联的稳定标识,或使某一个线程专用于某一个任务。

    周国庆

    2017/6/8

  • 相关阅读:
    PDF格式简单分析
    python 2.x 版本 pip 的使用
    网络读书笔记-运输层
    网络读书笔记-应用层
    线程池源码解析
    管道流创建订单
    @autowire、@resource原理
    Spring如何解决循环依赖
    结合Spring特性实现策略模式
    自定义注解+AOP实现redis分布式锁
  • 原文地址:https://www.cnblogs.com/tianqing/p/6961002.html
Copyright © 2020-2023  润新知