.NET多线程编程(15)——多线程的自动管理

简介:
  在多线程中经常会出现两种情况:
一种情况: 应用中线程把大部分时间花费在等待状态等待某个事件发生然后才能给予响应,这般使用ThreadPool(线程池)来解决;
另种情况:线程平时都处于休眠状态只是周期性地被唤醒,这一般使用Timer(定时器)来解决;
ThreadPool类提供个由系统维护线程池(可以看作个线程容器)该容器需要 Windows 2000 以上系统支持其中某些思路方法了只有高版本Windows才有API
将线程安放在线程池里需使用ThreadPool.QueueUserWorkItem思路方法该思路方法原型如下:
//将个线程放进线程池该线程Start思路方法将WaitCallback代理对象代表
public bool QueueUserWorkItem(WaitCallback);
//重载思路方法如下参数object将传递给WaitCallback所代表思路方法
public bool QueueUserWorkItem(WaitCallback, object);
注意:
ThreadPool类是个静态类你不能也不必要生成它对象而且旦使用该思路方法在线程池中添加了个项目那么该项目将是无法取消
在这里你无需自己建立线程只需把你要做工作写成然后作为参数传递给
ThreadPool.QueueUserWorkItem思路方法就行了传递思路方法就是依靠WaitCallback代理对象而线程建立、管理、运行等工作都是由系统自动完成你无须考虑那些复杂细节问题
ThreadPool 使用方法:
首先创建了个ManualReEvent对象该对象就像个信号灯可以利用它信号来通知其它线程
  本例中当线程池中所有线程工作都完成以后ManualReEvent对象将被设置为有信号从而通知主线程继续运行
ManualReEvent对象有几个重要思路方法:
  化该对象时用户可以指定其默认状态(有信号/无信号);
在化以后该对象将保持原来状态不变直到它Re或者Set思路方法被:
Re思路方法:将其设置为无信号状态;
Set思路方法:将其设置为有信号状态
WaitOne思路方法:使当前线程挂起直到ManualReEvent对象处于有信号状态此时该线程将被激活然后将向线程池中添加工作项这些以形式提供工作项被系统用来化自动建立线程当所有线程都运行完了以后ManualReEvent.Set思路方法被了ManualReEvent.WaitOne思路方法而处在等待状态主线程将接收到这个信号于是它接着往下执行完成后边工作
ThreadPool 使用方法举例:
using;
using.Collections;
using.Threading;
ThreadExample
{
//这是用来保存信息数据结构将作为参数被传递
publicSomeState
{
publicCookie;
publicSomeState(iCookie)
{
Cookie=iCookie;
}
}
publicAlpha
{
publicHashtableHashCount;
publicManualReEventeventX;
publiciCount=0;
publiciMaxCount=0;
publicAlpha(MaxCount)
{
HashCount=Hashtable(MaxCount);
iMaxCount=MaxCount;
}
//线程池里线程将Beta思路方法
publicvoidBeta(Objectstate)
{
//输出当前线程hash编码值和Cookie值
Console.WriteLine("{0}{1}:",Thread.CurrentThread.GetHashCode,((SomeState)state).Cookie);

Console.WriteLine("HashCount.Count{0},Thread.CurrentThread.GetHashCode{1}",HashCount.Count,Th
read.CurrentThread.GetHashCode);
lock(HashCount)
{
//如果当前Hash表中没有当前线程Hash值则添加的
(!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode))
HashCount.Add(Thread.CurrentThread.GetHashCode,0);
HashCount[Thread.CurrentThread.GetHashCode]=
(()HashCount[Thread.CurrentThread.GetHashCode])+1;
}
iX=2000;
Thread.Sleep(iX);
//Interlocked.Increment操作是个原子操作具体请看下面介绍说明
Interlocked.Increment(refiCount);
(iCountiMaxCount)
{
Console.WriteLine;
Console.WriteLine("SettingeventX");
eventX.Set;
}
}
}
publicSimplePool
{
publicMain(args)
{
Console.WriteLine("ThreadPoolSample:");
boolW2K=false;
MaxCount=10;//允许线程池中运行最多10个线程
//新建ManualReEvent对象并且化为无信号状态
ManualReEventeventX=ManualReEvent(false);
Console.WriteLine("Queuing{0}itemstoThreadPool",MaxCount);
AlphaoAlpha=Alpha(MaxCount);
//创建工作项
//注意化oAlpha对象eventX属性
oAlpha.eventX=eventX;
Console.WriteLine("QueuetoThreadPool0");
try
{
//将工作项装入线程池
//这里要用到Windows2000以上版本才有API所以可能出现NotSupportException异常
ThreadPool.QueueUserWorkItem(WaitCallback(oAlpha.Beta),SomeState(0));
W2K=true;
}
catch(NotSupportedException)
{
Console.WriteLine("TheseAPI'smayfailwhencalledonanon-
Windows2000system.");
W2K=false;
}
(W2K)//如果当前系统支持ThreadPool思路方法.
{
for(iItem=1;iItem<MaxCount;iItem)
{
//插入队列元素
Console.WriteLine("QueuetoThreadPool{0}",iItem);

ThreadPool.QueueUserWorkItem(WaitCallback(oAlpha.Beta),SomeState(iItem));
}
Console.WriteLine("WaitingforThreadPooltodrain");
//等待事件完成即线程ManualReEvent.Set思路方法
eventX.WaitOne(Timeout.Infinite,true);
//WaitOne思路方法使它线程等待直到eventX.Set思路方法被
Console.WriteLine("ThreadPoolhasbeendrained(Eventfired)");
Console.WriteLine;
Console.WriteLine("Loadacrossthreads");
foreach(objectoinoAlpha.HashCount.Keys)
Console.WriteLine("{0}{1}",o,oAlpha.HashCount[o]);
}
Console.ReadLine;
0;
}
}
}
}
中应该引起注意地方:
  SomeState类是个保存信息数据结构它在中作为参数被传递给每个线程你需要把些有用信息封装起来提供
给线程而这种方式是非常有效
出现InterLocked类也是专为多线程而存在它提供了些有用原子操作
原子操作:就是在多线程中如果这个线程这个操作修改个变量那么其他线程就不能修改这个变量了这跟lock关键字在本质上是样
输出结果:
ThreadPoolSample:
Queuing10itemstoThreadPool
QueuetoThreadPool0
QueuetoThreadPool1
QueuetoThreadPool2
QueuetoThreadPool3
QueuetoThreadPool4
QueuetoThreadPool5
20:
HashCount.Count0,Thread.CurrentThread.GetHashCode2
QueuetoThreadPool6
QueuetoThreadPool7
QueuetoThreadPool8
QueuetoThreadPool9
WaitingforThreadPooltodrain
41:
HashCount.Count1,Thread.CurrentThread.GetHashCode4
62:
HashCount.Count1,Thread.CurrentThread.GetHashCode6
73:
HashCount.Count1,Thread.CurrentThread.GetHashCode7
24:
HashCount.Count1,Thread.CurrentThread.GetHashCode2
85:
HashCount.Count2,Thread.CurrentThread.GetHashCode8
96:
HashCount.Count2,Thread.CurrentThread.GetHashCode9
107:
HashCount.Count2,Thread.CurrentThread.GetHashCode10
118:
HashCount.Count2,Thread.CurrentThread.GetHashCode11
49:
HashCount.Count2,Thread.CurrentThread.GetHashCode4
SettingeventX
ThreadPoolhasbeendrained(Eventfired)
Loadacrossthreads
111
101
91
81
71
61
42
22
我们应该彻底地分析上面把握住线程池本质理解它存在意义是什么这样才能得心应手地使用它




本文转自 qianshao 51CTO博客,原文链接:http://blog.51cto.com/qianshao/203216,如需转载请自行联系原作者

目录
相关文章
|
10天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
21天前
|
存储 缓存 NoSQL
Redis单线程已经很快了6.0引入多线程
Redis单线程已经很快了6.0引入多线程
31 3
|
24天前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
57 0
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
1月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法
|
1月前
|
Java C#
C#学习系列相关之多线程(五)----线程池ThreadPool用法
C#学习系列相关之多线程(五)----线程池ThreadPool用法
|
1月前
|
存储 安全 Java
深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践
线程使程序能够通过同时执行多个任务而更有效地运行。 线程可用于在不中断主程序的情况下在后台执行复杂的任务。 创建线程 有两种创建线程的方式。 扩展Thread类 可以通过扩展Thread类并覆盖其run()方法来创建线程:
103 1
深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践
|
1月前
|
并行计算 安全 Java
C# .NET面试系列四:多线程
<h2>多线程 #### 1. 根据线程安全的相关知识,分析以下代码,当调用 test 方法时 i > 10 时是否会引起死锁? 并简要说明理由。 ```c# public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } ``` 在给定的代码中,不会发生死锁。死锁通常是由于两个或多个线程互相等待对方释放锁而无法继续执行的情况。在这个代码中,只有一个线程持有锁,且没有其他线程参与,因此不
102 3
|
1月前
|
缓存 安全 Java
保障线程安全性:构建可靠的多线程应用
保障线程安全性:构建可靠的多线程应用
|
1月前
|
数据采集 存储 Java
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!

热门文章

最新文章