多线程(3)ThreadPool
使用Thread类已经可以创建并启动线程了,但是随着开启的线程越来越多,线程的创建和终止都需要手动操作,非常繁琐,另一个问题是,开启更多新的线程但是没有用的线程没有及时得到终止的时候,会占用越来越多的系统资源,影响性能。
所以,.net为我们引入了ThreadPool(线程池),我们只需要把要执行的任务放到线程池中即可,线程的开启包括资源的释放都由线程池帮我们完成。下面看一下怎么使用线程池。
线程池ThreadPool
核心类:System.Threading.ThreadPool, 线程池受.Net CLR管理的,每一个CLR都有一个线程池实例。
每个进程都有一个线程池,线程池的默认大小为:每个可用的处理器有 25 个线程。使用 SetMaxThreads 方法可以更改线程池中的线程数。每个线程使用默认的堆栈大小并按照默认的优先级运行。
ThreadPool类型拥有一个QueueUserWorkItem的静态方法。该静态方法接收一个委托,代表用户自定义的一个异步操作。在改方法被调用后,委托会进入到内部队列中。如果线程池中没有任何线程,将创建一个新的工作者线程(worker thread)并将队列中的第一个委托放入到该工作者线程中。
如果向线程池中放入新的操作,当之前的所有操作完成后,很可能只需重用一个线程来执行这些新的操作。如果QueueUserWorkItem执行的频率过快,线程池将创建更多的线程来执行这些新放入的异步委托。
线程池中的线程数是有限的,如果没有空闲的线程来执行这些异步委托操作,这种情况下,新的异步委托操作将在线程池的内部队列中等待,直到线程池中年的工作者线程空闲(有能力)来执行。
当停止向线程池中放入新的异步委托操作时,线程池会删除一定事件后过期的不在使用的线程,同时释放不再使用的系统资源。
线程池的使用非常简单,如下代码:
namespace ConsoleApplication18
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main thread starting..."); //1,不带参数
ThreadPool.QueueUserWorkItem(AsyncAction);
Thread.Sleep(TimeSpan.FromMilliseconds()); //2,带参数
ThreadPool.QueueUserWorkItem(AsyncAction, "Async state");
Thread.Sleep(TimeSpan.FromMilliseconds()); //3,lambda表达式
ThreadPool.QueueUserWorkItem(item =>
{
Console.WriteLine("Sub thread starting...");
Console.WriteLine("Action state:" + item ?? string.Empty);
Console.WriteLine(string.Format("Current thread id:{0}", Thread.CurrentThread.ManagedThreadId));
}, "Lambda state");
Thread.Sleep(TimeSpan.FromMilliseconds()); Console.WriteLine("Main thread completed!");
Console.ReadKey();
} /// <summary>
/// 委托匹配方法
/// </summary>
/// <param name="obj"></param>
static void AsyncAction(Object obj)
{
Console.WriteLine("Sub thread starting...");
Console.WriteLine("Action state:" + obj ?? string.Empty);
Console.WriteLine(string.Format("Current thread id:{0}", Thread.CurrentThread.ManagedThreadId));
} }
}
输出结果:

不适合使用线程池的场景
使用线程池创建线程这么简单,然后性能又好,是不是以后创建线程都去使用线程池呢?答案是否定的。
那么,以下场景是不适合使用线程池,而是自己创建并管理线程:
- 需要前台线程时。因为线程池默认创建的都是后台线程。
- 需要线程具有特定的优先级。因为放到线程池中的线程都是由线程池来调度的,无法对其优先级进行设置。
- 需要长时间运行的任务。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
多线程(3)ThreadPool的更多相关文章
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- 【多线程】-ThreadPool线程池
ThreadPool介绍: Thread类是一个静态类,所有不存在实例化构造函数操作,直接可以调用其内所存在的方法. 微软官网给出的解释: 提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 ...
- .net 多线程 Thread ThreadPool Task
先准备一个耗时方法 /// <summary>/// 耗时方法/// </summary>/// <param name="name">< ...
- 异步多线程 Thread ThreadPool Task
一.线程 Thread ThreadPool 线程是Windows任务调度的最小单位,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以 ...
- .NET多线程(Thread,ThreadPool,Task,Async与Await)
.NET多线程是什么? 进程与线程 进程是一种正在执行的程序. 线程是程序中的一个执行流. 多线程是指一个程序中可以同时运行多个不同的线程来执行不同的任务. .NET中的线程 Thread是创建和控制 ...
- .Net进阶系列(10)-异步多线程综述(被替换)
一. 综述 经过两个多个周的整理,异步多线程章节终于整理完成,如下图所示,主要从基本概念.委托的异步调用.Thread多线程.ThreadPool多线程.Task.Parallel并行计算.async ...
- java 中多线程和锁的使用以及获取多线程执行结果
多线程一:原生的写法 关键词 implements 实现 Runnable 类 run() 方法 注意点 : 创建类的实例 InterfaceController inter=new Int ...
- 多线程、多进程、协程、IO多路复用请求百度
最近学习了多线程.多进程.协程以及IO多路复用,那么对于爬取数据来说,这几个方式哪个最快呢,今天就来稍微测试一下 普通方式请求百度5次 import socket import time import ...
- python多线程批量下载远程图片
python多线程使用场景:多线程采集, 以及性能测试等 . 数据库驱动类-简单封装下 mysqlDriver.py #!/usr/bin/python3 #-*- coding: utf-8 -*- ...
随机推荐
- Ajax验证用户名是否被注册
Ajax验证用户名是否被注册 var xmlHttp; function createXMLHttpRequest(){ // 创建XMLHttp请求对象 if(window.ActiveXObjec ...
- .NET Core多平台开发体验[3]: Linux (Windows Linux子系统)
如果想体验Linux环境下开发和运行.NET Core应用,我们有多种选择.一种就是在一台物理机上安装原生的Linux,我们可以根据自身的喜好选择某种Linux Distribution,目前来说像R ...
- [Swift]LeetCode467. 环绕字符串中唯一的子字符串 | Unique Substrings in Wraparound String
Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz" ...
- [Swift]LeetCode1000. 合并石头的最低成本 | Minimum Cost to Merge Stones
There are N piles of stones arranged in a row. The i-th pile has stones[i] stones. A move consists ...
- Mysql、Hbuilder、Idea快捷键
MyEclipse 快捷键 ↑ ↓ ← →多 1.方法抽取,Alt+Shift+M 2.多行注释:Ctrl+Shift+/ 3.对象.方法; Ctrl+2 + ↓+回车 ,自动生成返回类型和变量 (非 ...
- Linux启动Redis失败/没有那个文件或目录
没有那个文件或目录问题,可能是你选择的目录不对. 应切换到Redis目录下启动.
- SpringBoot环境搭建
创建 maven 项目 , 选择的打包类型为 jar 类型 自己构建 SpringBoot 项目时 , 要继承 SpringBoot 的父项目 , 这里用的版本是 2.1.4 点击 Finish , ...
- Python档案袋(异常与异常捕获 )
无异常捕获 程序遇到异常会中断 print( xxx ) print("---- 完 -----") 得到结果为: 有异常捕获 程序遇到异常会进入异常处理,并继续执行下面程序 tr ...
- MySQL将utf8字符集改为utf8mb4
前言 今天在查看tomcat日志时发现了一个错误:Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x82\xF0 ...
- 免费IPv6访问收费IPv4,校园网免流量
软件:马上6 介绍: “可以让用户在免费的IPv6网络环境,有具备访问收费的IPv4互联网内容的能力!节省校园网流量!使用马上6客户端软件之后可以访问的IPv4互联网的内容(包括视频.游戏.音乐.学习 ...