前面文章已经介绍了如何使用线程,当每新建一个线程都需要占用内存空间和其他资源,销毁回收线程也需要资源,这对频繁使用线程是不友好的,于是便出现了线程池,线程池中会根据设定挂起几个线程,它们不会自动消除,始终存在,当需要线程时,直接使用线程池中的线程,使用结束后也不会销毁,这样就节约了很多资源。
二、ThreadPool使用介绍 1 使用线程池ThreadPool启用线程方法: QueueUserWorkItem(WaitCallback callBack, object state),callBack为执行的方法,state对象对可选参数。
static void Main(string[] args)
{
Console.WriteLine($"********************* 系统开始 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH: mm:ss.fff")} ***************");
ThreadPool.QueueUserWorkItem(obj =>
{
Calculate("Test");
Console.WriteLine(obj);
}, "State");
Console.WriteLine($"********************* 系统结束 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH: mm:ss.fff")} ***************");
}
static void Calculate(string name)
{
Console.WriteLine($"********************* 线程-{name}开始 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
long num = 0;
for (int i = 0; i < 10000000; i++)
{
num += i;
}
//等待2s
Thread.Sleep(2000);
Console.WriteLine($"********************* 线程-{name}结束 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
2 其他常用方法
| 方法名 | 描述 |
|---|---|
| GetMaxThreads | 获取线程池中辅助线程的最大数目和异步 I/O 线程的最大数目 |
| GetMinThreads | 获取线程池中辅助线程的最小数目和异步 I/O 线程的最小数目 |
| SetMaxThreads | 设置线程池最大线程数和最大空闲异步 I/O 线程数 |
| SetMinThreads | 设置线程池最小线程数和最小空闲异步 I/O 线程数 |
int workerMaxThreads;
int completionPortMaxThreads;
ThreadPool.GetMaxThreads(out workerMaxThreads, out completionPortMaxThreads);
Console.WriteLine($"线程池中辅助线程的最大数目:{workerMaxThreads}; 线程池中异步 I/O 线程的最大数目:{completionPortMaxThreads}");
int workerMinThreads;
int completionPortMinThreads;
ThreadPool.GetMinThreads(out workerMinThreads, out completionPortMinThreads);
Console.WriteLine($"线程池中辅助线程的最小数目:{workerMinThreads}; 线程池中异步 I/O 线程的最小数目:{completionPortMinThreads}");
//最小线程数和最小空闲异步 I/O 线程数
ThreadPool.SetMinThreads(4, 4);
//最大线程数和最大空闲异步 I/O 线程数
ThreadPool.SetMaxThreads(6, 6);
ThreadPool.GetMaxThreads(out workerMaxThreads, out completionPortMaxThreads);
Console.WriteLine($"线程池中辅助线程的最大数目:{workerMaxThreads}; 线程池中异步 I/O 线程的最大数目:{completionPortMaxThreads}");
ThreadPool.GetMinThreads(out workerMinThreads, out completionPortMinThreads);
Console.WriteLine($"线程池中辅助线程的最小数目:{workerMinThreads}; 线程池中异步 I/O 线程的最小数目:{completionPortMinThreads}");
搞这么多方法,怎么用呢?
static void Main(string[] args)
{
int workerMaxThreads;
int completionPortMaxThreads;
int workerMinThreads;
int completionPortMinThreads;
//最大线程数和最大空闲异步 I/O 线程数
ThreadPool.SetMaxThreads(6, 6);
ThreadPool.GetMaxThreads(out workerMaxThreads, out completionPortMaxThreads);
Console.WriteLine($"线程池中辅助线程的最大数目:{workerMaxThreads}; 线程池中异步 I/O 线程的最大数目:{completionPortMaxThreads}");
ThreadPool.GetMinThreads(out workerMinThreads, out completionPortMinThreads);
Console.WriteLine($"线程池中辅助线程的最小数目:{workerMinThreads}; 线程池中异步 I/O 线程的最小数目:{completionPortMinThreads}");
//启用8个线程,但线程池最多只能同时存在6个
for (int i = 0; i < 8; i++)
{
int k = i + 1;
ThreadPool.QueueUserWorkItem(obj =>
{
Calculate("Test" + k);
});
}
Console.WriteLine($"********************* 系统结束 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH: mm:ss.fff")} ***************");
}
static void Calculate(string name)
{
Console.WriteLine($"********************* 线程-{name}开始 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
long num = 0;
for (int i = 0; i < 10000000; i++)
{
num += i;
}
//等待2s
Thread.Sleep(2000);
Console.WriteLine($"********************* 线程-{name}结束 线程ID:{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
这里我们启用了8个线程,但是线程池设置了最多只能同时允许6个线程允许,所以只能等前6个线程最先运行完的2个空出资源第7,8个方法才可以执行。这样看线程池是不是更友好,当你同时启用100个甚至更多个线程(我没试过哦),可能一下电脑卡死,站点挂掉啥的,但有了线程池就不用怕了。



