线程生命周期
线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。
下面列出了线程生命周期中的各种状态:
未启动状态: 当线程实例被创建但 Start 方法未被调用时的状况。
就绪状态: 当线程准备好运行并等待 CPU 周期时的状况。
不可运行状态: 下面的几种情况下线程是不可运行的:
已经调用 Sleep 方法
已经调用 Wait 方法
通过 I/O 操作阻塞
死亡状态: 当线程已完成执行或已中止时的状况。
主线程
在 C# 中,System.Threading.Thread 类用于线程的工作。它允许创建并访问多线程应用程序中的单个线程。进程中第一个被执行的线程称为主线程。
当 C# 程序开始执行时,主线程自动创建。使用 Thread 类创建的线程被主线程的子线程调用。您可以使用 Thread 类的 CurrentThread 属性访问线程。
Example:
1
2
3
4
5
6
7
static void Main(string[] args)
{
Thread th = Thread.CurrentThread;
th.Name = "MainThread";
Console.WriteLine("This is {0}", th.Name);
Console.ReadKey();
}
运行结果:
1
This is MainThread
创建线程
1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
Thread t = new Thread(Child);
t.Start();
Console.WriteLine("This is main thread.");
Console.ReadKey();
}
static void Child()
{
Console.WriteLine("This is in thread.");
}
运行结果:
1
2
This is main thread.
This is in thread.
程序运行的结果不能保证哪个先输出,因为线程是由操作系统调度,每次哪个线程在前面可以不同
线程管理
Sleep()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void Main(string[] args)
{
Thread t = new Thread(Child);
t.Start();
Console.WriteLine("This is main thread.");
Console.ReadKey();
}
static void Child()
{
Console.WriteLine("This is in thread.");
Thread.Sleep(1000);
Console.WriteLine("Sleep 1 second.");
}
传入参数
1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
Thread t2 = new Thread(ChildWithParam);
t2.Start("test");
Console.ReadKey();
}
static void ChildWithParam(object str)
{
Console.WriteLine("Child with parameter: " + str.ToString());
}
上面创建的线程是类型不安全的,那用什么样的方式执行带传入参数的线程的方法是类型安全的呢,答案就是创建一个自定义类,在类中定义一个作为传入参数的字段,将线程的主方法定义为一个类的实例方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void Main(string[] args)
{
ThreadClass<string> testClass = new ThreadClass<string>("data");
Thread t3 = new Thread(testClass.ThreadFun);
t3.Start();
Console.ReadKey();
}
class ThreadClass<T>
{
private T data;
public ThreadClass(T data)
{
this.data = data;
}
public void ThreadFun()
{
Console.WriteLine("In thread class: " + this.data.ToString());
}
}
后台线程
Thread类默认创建的是前台线程,所以我们前面创建的线程全部都是前台线程。只要有一个前台线程在运行,应用程序的进程就在运行。如果有多个前台线程在运行,而Main()方法(主线程)结束了,应用程序的进程就仍然是激活的,直到所有前台线程完成其任务为止。
那后台线程呢?显然和前台线程相反。当主线程结束后,应用程序的进程就终止了,在所有前台线程结束后,后台线程就会被终止。
在编码的时候我们可以设置Thread类的IsBackground的属性来确定该线程是前台线程还是后台线程。当IsBackground设置为False的时候,为前台线程,设置为Ture的时候为后台线程。
线程池
线程池是可用于在后台执行多种任务的线程集合。
线程池通常用于服务器应用程序。 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会占用主线程,也不会延迟后续请求的处理。 一旦池中的线程完成任务,它将返回到等待线程队列中,等待被重复使用。 通过这种重复使用,应用程序可以避免产生为每个任务创建新线程的开销。
线程池通常具有最大线程数限制。 如果所有线程处于忙碌状态,则额外的任务将放入队列中,直到有线程可用时才能够得到处理
LR线程池