.Net组件程序设计之线程、并发管理(一)
1.线程
线程
线程的创建
线程的阻塞
线程挂起
线程睡眠
加入线程
线程中止
现在几乎所有的应用程序都是多线程的,给用户看来就是一个应用程序界面(应用程序线程),不管什么操作都不会导致界面出现响应慢的情况,这些都是多线程的功劳,有了多线程,可以让应用程序尽最大可能的处理更多的操作,调动很多线程来并行处理请求,这样会使得应用程序有更大的系统吞吐量。
1.线程
1.1线程
线程是什么呢?线程就是进程中的一条执行路径,每个应用程序至少在一个线程上运行。在本篇中将会对线程稍作讲解.
在.NET中,线程是执行的基本单元。在.NET中的线程并非是操作系统中的物理线程,而是对物理线程的托管代码表示。
在.NET System.Threading命名空间下,有个Thread类型的类,它就是代表着托管线程。
1.2线程的创建
我们直接来看下线程创建的示例:
1
2
3
4
5
6
7
8
9
|
1
public
class
ThreadingMethodCase
2 {
3
public
static
void
ThreadingMethod()
4 {
5 Thread thread = Thread.CurrentThread;
6
int
threadid = thread.ManagedThreadId;
7 Console.WriteLine(thread.Name +
"ThreadID is "
+ threadid);
8 }
9 }
|
1
2
3
4
|
1 ThreadStart threadstart =
new
ThreadStart(ThreadingMethodCase.ThreadingMethod);
2 Thread thread =
new
Thread(threadstart);
3 thread.Name =
"SubThread"
;
4 thread.Start();
|
在.NET中创建一个线程首先需要线程方法,什么叫线程方法?首先线程是一个操作或是一组操作的表示,线程方法就是前面这句话中的【操作】。
这里先看一下Thread类型的构造函数接受了一个ThreadStart类型的无参数委托,这个是好理解的。
线程创建了必须要显示的调用它的Start()函数才能开始执行线程。调用Strat()函数是不会对当前线程造成阻塞的,就是说在调用了之后控制权会立刻的回到当前的线程的客户端中。
1.3线程的阻塞
1.3.1线程挂起
1
2
3
4
5
6
|
1
public
sealed
class
Thread
2 {
3
public
void
Suspend();
4
public
void
Resume();
5 ……
6 }
|
Suspend()方法是挂起线程的执行.
Resume()方法则是释放挂起的线程,让线程继续执行在调用Suspend()方法的时候,是不会造成当前线程阻塞的,在调用后,控制权立即返回的,而且在要被挂起的线程中, 也不是被立即挂起的,而是在执行到一个安全点的时候,才会执行挂机操作的。什么是安全点?举个例子吧,假如要被挂起的线程中 正在执行一个函数的时候,外部被通知命令,要被挂起,这个时候线程是不会被挂起的,当这个函数执行完毕的时候,线程则会被挂起, 假设编辑器是把安全点插设在每个函数的末端的。
.NET中是不推荐我们使用这两个函数的,因为会造成很多方面的不稳定。
1.3.2线程睡眠
1
2
3
4
5
6
|
1
public
sealed
class
Thread
2 {
3
public
static
void
Sleep(
int
millisecondsTimeout);
4
public
static
void
Sleep(TimeSpan timeout);
5 ……
6 }
|
Sleep()是静态函数,是一个阻塞调用并且使当前线程放弃CPU时间片,就是在休眠指定的时间后,控制权才会返回到调用的线程。
Thread.Sleep(20);//让当前调用线程休眠20毫秒
Thread类还提供了另一种类似于休眠的操作:
1 public static void SpinWait(int iterations);
调用SpinWait()也是会造成当前阻塞的,但是当前线程不会放弃CPU时间片,而是在等待有限的时间(参数设置)后继续执行, 这种函数是在可控的情况下才去这样调用的,比如说当前线程要使用一个资源,而这个资源在被其他线程使用,那么就可以使用 SpinWait()函数,在等待有限的时间后,再去读取资源,如果资源还没被其他线程释放,当前线程也会继续执行,所有这是用于可控的情况下的方法。
1.3.3 加入线程
Thread类的Join()方法可以让一个线程等待另一个线程的终结。
这句定义什么意思呢?说是说不清的,来看一下Thread.Join()示例代码 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
1
public
class
StudyCase
2 {
3
public
void
ThreadingTest()
4 {
5 ThreadStart threadstart =
new
ThreadStart(ThreadingMethodCase.ThreadingMethod);
6 Thread thread =
new
Thread(threadstart);
7 thread.Name =
"newThread"
;
8 Thread.CurrentThread.Name =
"CurrentThread"
;
9
for
(
int
i = 0; i < 5; i++)
10 {
11
if
(i == 0)
12 {
13 thread.Start();
14 thread.Join();
15 }
16 Console.WriteLine(Thread.CurrentThread.Name+
"_"
+i.ToString());
17 }
18 }
19
20 }
|
1
2
3
4
5
6
7
8
9
|
1
public
class
ThreadingMethodCase
2 {
3
public
static
void
ThreadingMethod()
4 {
5 Thread thread = Thread.CurrentThread;
6
int
threadid = thread.ManagedThreadId;
7 Console.WriteLine(thread.Name +
"ThreadID is "
+ threadid);
8 }
9 }
|
从上图的结果再结合代码看一下,就大概的清楚了Join的意思了,意义就是阻塞当前线程,等待子线程(ThreadingTest函数中的thread变量)执行完毕时,当前线程再执行。
1.3.4线程中止
调用Thread类型提供的Abort()方法可以中止线程的运行,并且被中止的线程会抛出一个ThreadAbortException类型的异常。下面的示例代码会清晰的描述和示例代码结果图。
来看示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
1
public
class
ThreadingMethodCase
2 {
3
public
static
void
ThreadingMethodDiv()
4 {
5
try
6 {
7
while
(
true
)
8 {
9 Console.WriteLine(
"测试子线程中止"
);
10 }
11 }
12
catch
(ThreadAbortException abex)
13 {
14 Console.WriteLine(Thread.CurrentThread.Name+
"-子线程内部-"
+ abex.Message);
15 }
16 }
17 }
18
public
class
StudyCase
19 {
20
public
void
ThreadingTestAbort()
21 {
22 Thread.CurrentThread.Name=
"CurrentThread"
;
23 ThreadStart threadstart =
new
ThreadStart(ThreadingMethodCase.ThreadingMethod);
24 Thread thread =
new
Thread(threadstart);
25 thread.Name =
"newThread"
;
26
27 thread.Start();
28
for
(
int
i = 0; i < 10; i++)
29 {
30 Console.WriteLine(i.ToString());
31 }
32 thread.Abort();
33 thread.Join();
34
35 Console.WriteLine(
"当前线程"
);
36 }
37
38 }
|
将在下一章讲解线程同步。
本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1421962,如需转载请自行联系原作者