为什么要创建线程池?
线程池属于对象池.所有对象池都具有一个非常重要的共性,就是为了最大程度复用对象.那么,线程池的最重要的特征也就是最大程度利用线程。所以线程池的目的就是为了减少创建和切换线程的额外开销,利用已经的线程多次循环执行多个任务从而提高系统的处理能力。
在ASP.NET工作进程中有两种线程池,Worker线程池处理所有传入的请求, I / O线程池处理的I / O(访问文件系统,Web服务和数据库等)。每个应用程序域都有其自己的线程池,可以排队到线程池的操作的数量只受可用内存的限制,然而,对线程池中的线程数的限制在这个过程中可以同时被激活。
当我们发出一个(异步)页面请求。一个Worker线程就会被从Worker线程池中取出, 这个Worker线程会触发I/O操作。当I/O操作开始时,另一个线程将会被从I/O线程池中取出,在收到I/O线程的返回值之前,Worker线程会一直处于闲置状态。所以,如果你的页面加载事件触发了多个I/O操作,那么,Worker线程就很可能会被闲置很长时间。而线程池能够把正处于闲置状态的Worker线程回收,使他能够为其他的页面请求提供服务。从而,降低系统开销。
演示demo(创建控制台项目):
测试编码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace duo_0926 { class Program { static void Main(string[] args) { Thread t1 = new Thread(() => { Console.WriteLine("启动吃药的监听:输入1代表吃药"); Ation1(); }); t1.Start(); Thread t2 = new Thread(() => { Console.WriteLine("启动攻击的监听:输入2代表攻击"); Ation2(); }); t2.Start(); } /// <summary> /// 吃药的监听 /// </summary> public static void Ation1() { while (true) { string ctrl = Console.ReadLine(); if (ctrl.Equals("1")) { Console.WriteLine("吃药,血量增加200点。"); } } } /// <summary> /// 攻击的监听 /// </summary> public static void Ation2() { while (true) { string ctrl = Console.ReadLine(); if (ctrl.Equals("2")) { Console.WriteLine("攻击,对敌方造成200点伤害。"); } } } } }
当输入过快的时候无法被循环监听到:
一同运行,相当于两个线程会交替的进行执行。故而会出现如上现象。所以咱们开启线程的时候
演示代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace duo_0926 { class Program { static void Main(string[] args) { Thread t1 = new Thread(() => { Ation1(); }); t1.Start(); Thread t2 = new Thread(() => { Ation2(); }); t2.Start(); } /// <summary> /// 线程1 /// </summary> public static void Ation1() { for (int i = 0; i < 100; i++) { Console.WriteLine("线程1:"+i); } } /// <summary> /// 线程2 /// </summary> public static void Ation2() { for (int i = 0; i < 100; i++) { Console.WriteLine("线程2:" + i); } } } }
执行效果:
以上效果可以说明,两个线程是相互交替执行,并非共同执行。
所以说,如果进行同时监听,无法正确进行线程操作。
通过如下方法即可进行线程交互:
Thread.Sleep(1);//休息1毫秒,不争抢线程
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace duo_0926 { class Program { static void Main(string[] args) { Thread t1 = new Thread(() => { Ation1(); }); t1.Start(); Thread t2 = new Thread(() => { Ation2(); }); t2.Start(); } /// <summary> /// 线程1 /// </summary> public static void Ation1() { for (int i = 0; i < 100; i++) { Thread.Sleep(1); Console.WriteLine("线程1:"+i); } } /// <summary> /// 线程2 /// </summary> public static void Ation2() { for (int i = 0; i < 100; i++) { Thread.Sleep(1); Console.WriteLine("线程2:" + i); } } } }
可以看到,两个线程基本上都是在交互执行:
多次执行总会找到无法交互的地方。
说明线程休息的时间简短,线程1并没有争抢线程成功。可以加大线程休息时间。 Thread.Sleep(5);//每次线程休息5毫秒 重新测试,多次执行,出现争抢失败的情况就很少了:
重新测试监听
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace duo_0926 { class Program { static void Main(string[] args) { Thread t1 = new Thread(() => { Console.WriteLine("启动吃药的监听:输入1代表吃药"); Ation1(); }); t1.Start(); Thread t2 = new Thread(() => { Console.WriteLine("启动攻击的监听:输入2代表攻击"); Ation2(); }); t2.Start(); } /// <summary> /// 吃药的监听 /// </summary> public static void Ation1() { while (true) { Thread.Sleep(1); string ctrl = Console.ReadLine(); if (ctrl.Equals("1")) { Console.WriteLine("吃药,血量增加200点。"); } } } /// <summary> /// 攻击的监听 /// </summary> public static void Ation2() { while (true) { Thread.Sleep(1); string ctrl = Console.ReadLine(); if (ctrl.Equals("2")) { Console.WriteLine("攻击,对敌方造成200点伤害。"); } } } } }