线程:
线程的命名空间为:using System.Threading;
1. 创建线程
class Program
{
//main:程序的入口,clr一开始就会创建一个默认的主线程(前台线程),指向了Main方法;
static void Main(string[] args)
{
//Thread thread = new Thread(delegate() {
// while(true)
// {
// Console.WriteLine(DateTime.Now);
// Thread.Sleep(100);
// }
//}); //匿名函数
//线程的参数ThreadStart
//线程默认是前台线程;一个进程退出的标志位所有的前台线程都结束之后,
Thread thread = new Thread(ThreadMethod);
//更改线程为后台线程
//后台线程不会阻塞进程退出。
thread.IsBackground = true;
thread.Start();
//执行代码的线程等待thread线程执行完成。
//thread.Join(1000);//等待 thread线程执行完成,等待1秒钟。
//thread.Abort(); //不得已才能用,直接终结线程。会抛出异常。尽量不要用该方法。
//一般情况下,线程方法体执行完之后,线程会自动释放。
//主线程也不断的向控制台输出内容
while(true)
{
Console.WriteLine("from 主线程--------------");
Thread.Sleep(500);
}
}
static void ThreadMethod()
{
int i = 1;
while(true)
{
i++;
Console.WriteLine(DateTime.Now);
Thread.Sleep(500);
if (i >= 10)
{
break;
}
}
}
}
thread.Abort();
直接终止当前线程,一般情况下不使用该函数来终止线程,线程的方法体执行完之后会自动释放资源,终止线程。
2. 线程池:
线程池中的线程本身都是后台线程。
线程池的线程优势;线程可以进行重载。
static void Main(string[] args)
{
//线程池中的线程本身都是后台线程。
//线程池的线程优势:线程可以进行重载。
//
//WaitCallback 表示线程池要执行的回调方法。
ThreadPool.QueueUserWorkItem(s =>
{
Console.WriteLine(s);
},"ssssss");
Console.ReadKey();
}
线程池 VS 手动创建线程
1.启动一个线程: 开辟一个内存空间,1M内存。线程有可能占用部分的寄存器。
2.操作系统线程数非常多的时候,操作系统花费大量时间用在线程切换。
//线程池 VS 手动创建线程
//启动一个线程: 开辟一个内存空间,1M内存。线程有可能占用部分的寄存器。
//操作系统线程数非常多的时候,操作系统花费大量时间用在线程切换。
Stopwatch sw = new Stopwatch();
sw.Start();
for(var i=0;i<100;i++)
{
new Thread(() =>
{
int i1 = 0;
i1++;
//Console.WriteLine(++i1);
}).Start();
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalSeconds);
sw.Restart();
for (var i = 0; i < 10000; i++)
{
ThreadPool.QueueUserWorkItem((s) =>
{
int i1 = 0;
i1++;
//Console.WriteLine(++i1);
});
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalSeconds);
线程池内部实现原理:
线程池中的线程不能保证整体的请求项之间是请求处理的顺序。
什么时候用线程池,什么时候用手动创建线程?
- 能用线程池的就用线程池。(处理的顺序不确定。)
- 我们想手动关闭线程的话,那么必须手动创建线程。 Abort() Join() 方法,必须手动创建线程。
- 我们需要对线程池的线程的优先级做设置的情况下,只能使用手动创建线程。
- 如果执行的线程执行时间特别长。线程池和线程差不多。线程池适合做大量的小运算。