二十四线程和线程池

1、概念

1、概念

  1.0 线程的和进度的关联以及优缺点**

  1.0
线程的和过程的涉嫌以及优缺点**

  windows系统是一个四线程的操作系统。一个先后至少有一个历程,一个历程至少有一个线程。进程是线程的器皿,一个C#客户端程序开端于一个独立的线程,CLR(公共语言运行库)为该进程创制了一个线程,该线程称为主线程。例如当大家创立一个C#控制台程序,程序的输入是Main()函数,Main()函数是始于一个主线程的。它的效应重假若发出新的线程和实施顺序。C#是一门匡助多线程的编程语言,通过Thread类创立子线程,引入using
System.Threading命名空间。 

  windows系统是一个八线程的操作系统。一个程序至少有一个进度,一个进程至少有一个线程。进度是线程的容器,一个C#客户端程序开头于一个单身的线程,CLR(公共语言运行库)为该进度创设了一个线程,该线程称为主线程。例如当我们成立一个C#控制台程序,程序的入口是Main()函数,Main()函数是始于一个主线程的。它的作用重假诺发出新的线程和履行顺序。C#是一门协助多线程的编程语言,通过Thread类创立子线程,引入using
System.Threading命名空间。 

三八线程的优点 

四线程的亮点 

1
2
1、 多线程可以提高CPU的利用率,因为当一个线程处于等待状态的时候,CPU会去执行另外的线程
2、 提高了CPU的利用率,就可以直接提高程序的整体执行速度

?

二十多线程的瑕疵:

1
2
1、 多线程可以提高CPU的利用率,因为当一个线程处于等待状态的时候,CPU会去执行另外的线程
2、 提高了CPU的利用率,就可以直接提高程序的整体执行速度

 

四线程的症结:

1
2
3
1、线程开的越多,内存占用越大
2、协调和管理代码的难度加大,需要CPU时间跟踪线程
3、线程之间对资源的共享可能会产生可不遇知的问题

 

 

?

     1.1 前台线程和后台线程

1
2
3
1、线程开的越多,内存占用越大
2、协调和管理代码的难度加大,需要CPU时间跟踪线程
3、线程之间对资源的共享可能会产生可不遇知的问题

   
 
C#中的线程分为前台线程和后台线程,线程创建时不做设置暗许是前台线程。即线程属性IsBackground=false。

澳门葡京官方网站, 

Thread.IsBackground = false;//false:设置为前台线程,系统默认为前台线程。

     1.1 前台线程和后台线程

 不一致以及如何选拔:

   
 
C#中的线程分为前台线程和后台线程,线程成立时不做设置暗中认同是前台线程。即线程属性IsBackground=false。

    那两者的区分就是:应用程序必须运行完所有的前台线程才足以脱离;而对此后台线程,应用程序则足以不考虑其是或不是曾经运行达成而直接退出,所有的后台线程在应用程序退出时都会自行终止。一般后台线程用于拍卖时间较短的天职,如在一个Web服务器中得以接纳后台线程来拍卖客户端发过来的央浼音讯。而前台线程一般用于拍卖要求长日子等待的天职,如在Web服务器中的监听客户端请求的顺序。

Thread.IsBackground = false;//false:设置为前台线程,系统默认为前台线程。

线程是依托在经过上的,进度都终止了,线程也就流失了!

 分歧以及怎样选取:

假诺有一个前台线程未脱离,进程就不会终止!即说的就是先后不会倒闭!(即在资源管理器中可以看来进度未终止。)

    这两边的不相同就是:应用程序必须运行完所有的前台线程才足以退出;而对此后台线程,应用程序则足以不考虑其是还是不是已经运行落成而直白退出,所有的后台线程在应用程序退出时都会自动终止。一般后台线程用于拍卖时间较短的天职,如在一个Web服务器中可以使用后台线程来处理客户端发过来的呼吁音信。而前台线程一般用来拍卖须要长日子等待的义务,如在Web服务器中的监听客户端请求的次第。

     1.3 十二线程的创导

线程是依托在经过上的,进程都得了了,线程也就熄灭了!

   
上边的代码创设了一个子线程,作为程序的入口mian()函数所在的线程即为主线程,大家因此Thread类来创制子线程,Thread类有 ThreadStart 和
ParameterizedThreadStart类型的委托参数,大家也足以一贯写方法的名字。线程执行的章程可以传递参数(可选),参数的门类为object,写在Start()里。

若是有一个前台线程未脱离,进程就不会停下!即说的就是先后不会关闭!(即在资源管理器中可以见到进度未终止。)

澳门葡京官方网站 1

     1.3 二十四线程的始建

class Program
 {
        //我们的控制台程序入口是main函数。它所在的线程即是主线程
        static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程";
            //thread.Start("王建");                       //在此方法内传递参数,类型为object,发送和接收涉及到拆装箱操作
            thread.Start(); 
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter) //方法内可以有参数,也可以没有参数
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }
  }

   
上边的代码创建了一个子线程,作为程序的入口mian()函数所在的线程即为主线程,大家经过Thread类来成立子线程,Thread类有 ThreadStart 和
ParameterizedThreadStart类型的信托参数,大家也足以一向写方法的名字。线程执行的章程可以传递参数(可选),参数的档次为object,写在Start()里。

澳门葡京官方网站 2

澳门葡京官方网站 3😉

先是采用new
Thread()创设出新的线程,然后调用Start方法使得线程进入就绪状态,拿到系统资源后就执行,在履行进程中可能有等待、休眠、死亡和封堵多种状态。正常执行落成时间片后重回到就绪状态。假使调用Suspend方法会进去等待情状,调用Sleep或然碰到进度同步使用的锁机制而休眠等待。具体进程如下图所示:

class Program
 {
        //我们的控制台程序入口是main函数。它所在的线程即是主线程
        static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程";
            //thread.Start("王建");                       //在此方法内传递参数,类型为object,发送和接收涉及到拆装箱操作
            thread.Start(); 
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter) //方法内可以有参数,也可以没有参数
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }
  }

澳门葡京官方网站 4

澳门葡京官方网站 5😉

2、线程的基本操作

首先使用new
Thread()创设出新的线程,然后调用Start方法使得线程进入就绪状态,得到系统资源后就执行,在推行进度中恐怕有等待、休眠、长逝和堵塞七种情景。正常实施完结时间片后重回到就绪状态。尽管调用Suspend方法会进去等待情形,调用Sleep可能遭受进度同步使用的锁机制而休眠等待。具体进度如下图所示:

线程和其余常见的类一样,有着广大性质和情势,参考下表:

澳门葡京官方网站 6

澳门葡京官方网站 7

2、线程的基本操作

2.1 线程的相干属性

线程和别的常见的类一样,有着众多品质和情势,参考下表:

俺们可以透过地点表中的属性获取线程的局地唇齿相依音讯,下边是代码显示和输出结果:

澳门葡京官方网站 8

澳门葡京官方网站 9

2.1 线程的有关属性

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程"; 
            thread.Start();
            StringBuilder threadInfo = new StringBuilder();
            threadInfo.Append(" 线程当前的执行状态: " + thread.IsAlive);
            threadInfo.Append("\n 线程当前的名字: " + thread.Name);
            threadInfo.Append("\n 线程当前的优先级: " + thread.Priority);
            threadInfo.Append("\n 线程当前的状态: " + thread.ThreadState);
            Console.Write(threadInfo);
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }

大家可以透过上边表中的性质获取线程的局地荣辱与共新闻,上边是代码显示和输出结果:

澳门葡京官方网站 10

澳门葡京官方网站 11😉

 输输出结果: 澳门葡京官方网站 12

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程"; 
            thread.Start();
            StringBuilder threadInfo = new StringBuilder();
            threadInfo.Append(" 线程当前的执行状态: " + thread.IsAlive);
            threadInfo.Append("\n 线程当前的名字: " + thread.Name);
            threadInfo.Append("\n 线程当前的优先级: " + thread.Priority);
            threadInfo.Append("\n 线程当前的状态: " + thread.ThreadState);
            Console.Write(threadInfo);
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }

2.2 线程的相干操作

澳门葡京官方网站 13😉

  2.2.1 Abort()方法

 输输出结果: 

     Abort()方法用来终止线程,调用此措施强制甘休正在实践的线程,它会抛出一个ThreadAbortException万分从而导致目的线程的告一段落。上边代码演示:

澳门葡京官方网站 14

     

2.2 线程的有关操作

澳门葡京官方网站 15

  2.2.1 Abort()方法

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name);
            //开始终止线程
            Thread.CurrentThread.Abort();
            //下面的代码不会执行
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }

     Abort()方法用来终止线程,调用此措施强制甘休正在推行的线程,它会抛出一个ThreadAbortException极度从而造成目的线程的停下。上边代码演示:

澳门葡京官方网站 16

     

推行结果:和大家想象的相同,上面的轮回没有被实施澳门葡京官方网站 17

澳门葡京官方网站 18😉

 

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name);
            //开始终止线程
            Thread.CurrentThread.Abort();
            //下面的代码不会执行
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }

  2.2.2 ResetAbort()方法

澳门葡京官方网站 19😉

  
   Abort方法可以通过跑出ThreadAbortException万分中止线程,而利用ResetAbort方法可以收回中止线程的操作,下边通过代码演示使用 ResetAbort方法。

施行结果:和咱们想像的一模一样,上边的大循环没有被实施

澳门葡京官方网站 20

澳门葡京官方网站 21

     static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            try
            {
                Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name); 
         //开始终止线程
                Thread.CurrentThread.Abort();
            }
            catch(ThreadAbortException ex)
            {
                Console.WriteLine("我是:{0},我又恢复了", Thread.CurrentThread.Name);
         //恢复被终止的线程
                Thread.ResetAbort();
            }
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }

 

澳门葡京官方网站 22

  2.2.2 ResetAbort()方法

举办结果:澳门葡京官方网站 23

  
   Abort方法可以通过跑出ThreadAbortException万分中止线程,而利用ResetAbort方法可以收回中止线程的操作,下边通过代码演示使用 ResetAbort方法。

  2.2.3 Sleep()方法 

澳门葡京官方网站 24😉

      
Sleep()方法调已阻塞线程,是近年来线程进入休眠状态,在蛰伏进度中占有系统内存不过不占用系统时间,当休眠期将来,继续执行,申明如下:
 

     static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            try
            {
                Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name); 
         //开始终止线程
                Thread.CurrentThread.Abort();
            }
            catch(ThreadAbortException ex)
            {
                Console.WriteLine("我是:{0},我又恢复了", Thread.CurrentThread.Name);
         //恢复被终止的线程
                Thread.ResetAbort();
            }
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }
        public static void Sleep(TimeSpan timeout);          //时间段
        public static void Sleep(int millisecondsTimeout);   //毫秒数

澳门葡京官方网站 25😉

  实例代码: 

举办结果:

澳门葡京官方网站 26

澳门葡京官方网站 27

       static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            threadA.Start();
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }

  2.2.3 Sleep()方法 

澳门葡京官方网站 28

      
Sleep()方法调已阻塞线程,是当下线程进入休眠状态,在蛰伏进度中据为己有系统内存不过不占用系统时间,当休眠期从此,继续执行,表明如下:
 

将上边的代码执行今后,可以领略的看出每一遍循环之间相距300微秒的时辰。

        public static void Sleep(TimeSpan timeout);          //时间段
        public static void Sleep(int millisecondsTimeout);   //毫秒数

      2.2.4 join()方法

  实例代码: 

    
 Join方法紧如果用来阻塞调用线程,直到某个线程终止或透过了点名时间甘休。官方的演说比较平淡,通俗的说就是开创一个子线程,给它加了那些主意,别的线程就会一噎止餐实施,直到这些线程执行完甘休才去实践(包涵主线程)。她的点子表明如下:

 

 public void Join();
 public bool Join(int millisecondsTimeout);    //毫秒数
 public bool Join(TimeSpan timeout);       //时间段
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            threadA.Start();
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("[{2}] 我是:{0},我循环{1}次", Thread.CurrentThread.Name, i, DateTime.Now.ToString("HH:mm:ss.fff"));
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }
    }
}

为了印证方面所说的,大家首先看一段代码:  

将地点的代码执行今后,可以精晓的见到每一回循环之间距离300阿秒的时日。

澳门葡京官方网站 29

澳门葡京官方网站 30

static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            Thread threadB = new Thread(ThreadMethod);     //执行的必须是无返回值的方法  
            threadB.Name = "小B";
            threadA.Start();
       //threadA.Join();      
            threadB.Start();
       //threadB.Join();

            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:主线程,我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);          //休眠300毫秒                                                
            }
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }

 

澳门葡京官方网站 31

      2.2.4 join()方法

 

    
 Join方法紧假如用来阻塞调用线程,直到某个线程终止或透过了指定时间甘休。官方的诠释相比较平淡,通俗的说就是创立一个子线程,给它加了这么些主意,别的线程就会停顿实施,直到这一个线程执行完甘休才去实施(包含主线程)。她的点子表明如下:

因为线程之间的实践是轻易的,所有执行结果和我们想像的一致,杂乱无章!然则表达他们是同时举行的。澳门葡京官方网站 32

 public void Join();
 public bool Join(int millisecondsTimeout);    //毫秒数
 public bool Join(TimeSpan timeout);       //时间段

     将来大家把代码中的
 ThreadA.join()方法注释打消,首先程序中有多个线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先举办,执行达成之后ThreadB接着执行,最终才是主线程执行。

为了证实方面所说的,大家首先看一段代码:  

看执行结果:

澳门葡京官方网站 33😉

澳门葡京官方网站 34

static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            Thread threadB = new Thread(ThreadMethod);     //执行的必须是无返回值的方法  
            threadB.Name = "小B";
            threadA.Start();
       //threadA.Join();      
            threadB.Start();
       //threadB.Join();

            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:主线程,我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);          //休眠300毫秒                                                
            }
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }

        2.2.5 Suspent()和Resume()方法

澳门葡京官方网站 35😉

       其实在C# 2.0后头,
Suspent()和Resume()方法已经不合时宜了。suspend()方法简单生出死锁。调用suspend()的时候,目的线程会停下来,但却一如既往保有在那前边拿到的锁定。此时,其余任何线程都无法访问锁定的资源,除非被”挂起”的线程苏醒运行。对其余线程来说,固然它们想过来目标线程,同时又准备动用此外一个锁定的资源,就会促成死锁。所以不应当接纳suspend()。

 

 

因为线程之间的施行是随机的,所有执行结果和我们想像的一模一样,杂乱无章!不过表达她们是同时实施的。如下图

澳门葡京官方网站 36

澳门葡京官方网站 37

     static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "小A";  
            threadA.Start();  
            Thread.Sleep(3000);         //休眠3000毫秒      
            threadA.Resume();           //继续执行已经挂起的线程
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            Thread.CurrentThread.Suspend();  //挂起当前线程
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i); 
            }
        }

后天我们把代码中的  ThreadA.join()方法注释裁撤,在探望执行的功能啊!

澳门葡京官方网站 38

澳门葡京官方网站 39

 

首先程序中有五个线程,ThreadA、ThreadB、主线程,首先我们看来主线程和ThreadB线程阻塞,ThreadA先实施,而主线程和ThreadB线程则还要实施了。

       执行上边的代码。窗口并从未当即执行
ThreadMethod方法输出循环数字,而是等待了三分钟之后才输出,因为线程初阶实践的时候实施了Suspend()方法挂起。然后主线程休眠了3秒钟以往又经过Resume()方法复苏了线程threadA。

这就是说大家把代码中的
 ThreadA.join()方法和ThreadB.join()方法注释都收回,在探视执行的法力呢!

    2.2.6 线程的先期级

澳门葡京官方网站 40

  一经在应用程序中有三个线程在运转,但有的线程比另一部分线程主要,那种情况下能够在一个进度中为区其他线程指定区其余优先级。线程的预先级可以透过Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5个先行等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。公共语言运行库默许是Normal类型的。见下图:

从运行结果能够看来,首先程序中有多少个线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先进行,执行完结之后ThreadB接着执行,最终才是主线程执行。

澳门葡京官方网站 41

看实践结果:

直接上代码来看效用:

        2.2.5 Suspent()和Resume()方法

澳门葡京官方网站 42

       其实在C# 2.0之后,
Suspent()和Resume()方法已经过时了。suspend()方法简单生出死锁。调用suspend()的时候,目的线程会停下来,但却仍然有所在那从前得到的锁定。此时,其余任何线程都无法访问锁定的资源,除非被”挂起”的线程恢复生机运行。对其余线程来说,假若它们想重操旧业目的线程,同时又打算动用别的一个锁定的资源,就会促成死锁。所以不应有选择suspend()。

澳门葡京官方网站 43

 

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Priority = ThreadPriority.Highest;
            threadB.Priority = ThreadPriority.BelowNormal;
            threadB.Start();
            threadA.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod(new object());
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            for (int i = 0; i < 500; i++)
            { 
                Console.Write(Thread.CurrentThread.Name); 
            }
        }

澳门葡京官方网站 44😉

澳门葡京官方网站 45

     static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "小A";  
            threadA.Start();  
            Thread.Sleep(3000);         //休眠3000毫秒      
            threadA.Resume();           //继续执行已经挂起的线程
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            Thread.CurrentThread.Suspend();  //挂起当前线程
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i); 
            }
        }

执行结果:

澳门葡京官方网站 46😉

澳门葡京官方网站 47

 

上边的代码中有七个线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这点从运行结果中也足以看到,线程B
偶尔会并发在主线程和线程A前面。当有多少个线程同时远在可实施情形,系统优先执行优先级较高的线程,但这只象征优先级较高的线程占有越来越多的CPU时间,并不代表一定要先实施完优先级较高的线程,才会举行优先级较低的线程。

       执行上面的代码。窗口并从未及时执行
ThreadMethod方法输出循环数字,而是等待了三分钟之后才输出,因为线程起始推行的时候实施了Suspend()方法挂起。然后主线程休眠了3秒钟以往又经过Resume()方法苏醒了线程threadA。

预先级越高意味着CPU分配给该线程的时光片更多,执行时间就多

    2.2.6 线程的预先级

先行级越低表示CPU分配给该线程的时刻片越少,执行时间就少

  只要在应用程序中有多个线程在运作,但有些线程比另一部分线程主要,那种情状下得以在一个进度中为区其他线程指定差距的优先级。线程的预先级可以由此Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5个先行等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。公共语言运行库暗中认同是诺玛l类型的。见下图:

   3、线程同步

澳门葡京官方网站 48

  什么是线程安全:

一贯上代码来看功能:

  线程安全是指在当一个线程访问该类的某部数据时,举行珍惜,其余线程不只怕展开访问直到该线程读取完,其余线程才可应用。不会产出数量不等同可能数额污染。

澳门葡京官方网站 49澳门葡京官方网站 50

   线程有大概和其余线程共享一些资源,比如,内存,文件,数据库等。当多少个线程同时读写同一份共享资源的时候,可能会挑起争论。那时候,大家必要引入线程“同步”机制,即诸君线程之间要有个先来后到,不可以一窝蜂挤上去抢作一团。线程同步的诚实意思和字面意思恰好相反。线程同步的忠实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源举办操作,而不是还要开展操作。

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Priority = ThreadPriority.Highest;
            threadB.Priority = ThreadPriority.BelowNormal;
            threadB.Start();
            threadA.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod(new object());
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            for (int i = 0; i < 500; i++)
            { 
                Console.Write(Thread.CurrentThread.Name); 
            }
        }

缘何要促成联机啊,下边的事例大家拿知名的单例格局以来呢。看代码

View Code

澳门葡京官方网站 51

履行结果:

public class Singleton
    {
        private static Singleton instance; 
        private Singleton()   //私有函数,防止实例
        {

        } 
        public static Singleton GetInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

澳门葡京官方网站 52

澳门葡京官方网站 53

地点的代码中有八个线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这点从运行结果中也得以看出,线程B
偶尔会冒出在主线程和线程A后边。当有多少个线程同时高居可实施情形,系统优先执行优先级较高的线程,但那只象征优先级较高的线程占有愈来愈多的CPU时间,并不代表早晚要先实施完优先级较高的线程,才会进行优先级较低的线程。

     
 单例形式就是确保在全路应用程序的生命周期中,在任什么日期刻,被指定的类唯有一个实例,并为客户程序提供一个拿到该实例的大局访问点。但上边代码有一个精通的难点,那就是只要几个线程同时去取得这么些目的实例,那。。。。。。。。

先行级越高意味着CPU分配给该线程的日子片更加多,执行时间就多

我们队代码举办改动:

优先级越低表示CPU分配给该线程的小时片越少,执行时间就少

澳门葡京官方网站 54

   3、线程同步

public class Singleton
{
       private static Singleton instance;
       private static object obj=new object(); 
       private Singleton()        //私有化构造函数
       {

       } 
       public static Singleton GetInstance()
       {
               if(instance==null)
               {
                      lock(obj)      //通过Lock关键字实现同步
                      {
                             if(instance==null)
                             {
                                     instance=new Singleton();
                             }
                      }
               }
               return instance;
       }
}

  什么是线程安全:

澳门葡京官方网站 55

  线程安全是指在当一个线程访问该类的某部数据时,举办保证,其余线程不大概展开访问直到该线程读取完,其他线程才可应用。不会油不过生数量不等同只怕数额污染。

通过改动后的代码。加了一个
lock(obj)代码块。那样就可以达成同台了,如果不是很明亮的话,大家看前面继续教师~

   线程有大概和别的线程共享一些资源,比如,内存,文件,数据库等。当七个线程同时读写同一份共享资源的时候,大概会引起争论。这时候,大家须求引入线程“同步”机制,即诸君线程之间要有个先来后到,不可以一窝蜂挤上去抢作一团。线程同步的真实性意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:多少个线程之间要排队,一个一个对共享资源进行操作,而不是还要展开操作。

  3.0 使用Lock关键字贯彻线程同步 

干什么要完毕共同啊,下边的例证我们拿知名的单例形式以来呢。看代码

  率先制造八个线程,五个线程执行同一个方法,参考上边的代码:

澳门葡京官方网站 56😉

澳门葡京官方网站 57

public class Singleton
    {
        private static Singleton instance; 
        private Singleton()   //私有函数,防止实例
        {

        } 
        public static Singleton GetInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        { 
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);
            }
        }

澳门葡京官方网站 58😉

澳门葡京官方网站 59

     
 单例方式就是保证在全体应用程序的生命周期中,在任曾几何时刻,被指定的类唯有一个实例,并为客户程序提供一个得到该实例的大局访问点。但地点代码有一个备受关注的标题,那就是假设八个线程同时去拿到那一个指标实例,那。。。。。。。。

执行结果:

俺们队代码举办改动:

澳门葡京官方网站 60

澳门葡京官方网站 61😉

 

public class Singleton
{
       private static Singleton instance;
       private static object obj=new object(); 
       private Singleton()        //私有化构造函数
       {

       } 
       public static Singleton GetInstance()
       {
               if(instance==null)
               {
                      lock(obj)      //通过Lock关键字实现同步
                      {
                             if(instance==null)
                             {
                                     instance=new Singleton();
                             }
                      }
               }
               return instance;
       }
}

透过上边的执行结果,可以很清楚的观察,三个线程是在同时实施ThreadMethod这些法子,那明显不符合大家线程同步的渴求。大家对代码进行修改如下:

澳门葡京官方网站 62😉

澳门葡京官方网站 63

通过修改后的代码。加了一个
lock(obj)代码块。那样就可以完毕同步了,倘诺不是很明白的话,大家看前面继续教授~

澳门葡京官方网站 64

  3.0
使用Lock关键字贯彻
线程同步 

static void Main(string[] args)
        {
            Program pro = new Program();
            Thread threadA = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)             //添加lock关键字
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            } 
        }

  率先创设多少个线程,五个线程执行同一个艺术,参考上面的代码:

澳门葡京官方网站 65

澳门葡京官方网站 66😉

施行结果:

static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        { 
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);
            }
        }

澳门葡京官方网站 67

澳门葡京官方网站 68😉

俺们透过添加了 lock(this)
{…}代码,查看执行结果达成了俺们想要的线程同步须要。不过我们知道this表示如今类实例的自身,那么有诸如此类一种情景,大家把要求拜访的法门所在的花色进行三个实例A和B,线程A访问实例A的章程ThreadMethod,线程B访问实例B的措施ThreadMethod,那样的话仍能达到线程同步的要求吗。

推行结果:

澳门葡京官方网站 69

澳门葡京官方网站 70

澳门葡京官方网站 71

 

static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

由此地点的实施结果,可以很了然的观察,两个线程是在同时推行ThreadMethod这一个措施,那肯定不适合我们线程同步的渴求。大家对代码进行修改如下:

澳门葡京官方网站 72

澳门葡京官方网站 73澳门葡京官方网站 74

实施结果:

static void Main(string[] args)
        {
            Program pro = new Program();
            Thread threadA = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)             //添加lock关键字
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            } 
        }

澳门葡京官方网站 75

View Code

俺们会发现,线程又不曾兑现同步了!lock(this)对于那种处境是不行的!所以要求大家对代码进行改动!修改后的代码如下: 

推行结果:

澳门葡京官方网站 76

澳门葡京官方网站 77

澳门葡京官方网站 78

俺们透过添加了 lock(this)
{…}代码,查看执行结果落成了大家想要的线程同步须求。可是大家明白this表示近来类实例的本身,那么有如此一种情况,大家把须求拜访的形式所在的系列进行五个实例A和B,线程A访问实例A的方法ThreadMethod,线程B访问实例B的法子ThreadMethod,那样的话还是可以达到线程同步的须求吗。

private static object obj = new object();
        static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

澳门葡京官方网站 79澳门葡京官方网站 80

澳门葡京官方网站 81

static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

由此翻看执行结果。会意识代码完结了大家的必要。那么 lock(this)
和lock(Obj)有哪些分别吧? 

View Code

lock(this) 锁定 当前实例对象,如果有多个类实例的话,lock锁定的只是当前类实例,对其它类实例无影响。所有不推荐使用。 
lock(typeof(Model))锁定的是model类的所有实例。 
lock(obj)锁定的对象是全局的私有化静态变量。外部无法对该变量进行访问。 
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 
所以,lock的结果好不好,还是关键看锁的谁,如果外边能对这个谁进行修改,lock就失去了作用。所以一般情况下,使用私有的、静态的并且是只读的对象。

施行结果:

总结:

澳门葡京官方网站 82

1、lock的是必须是援引类型的目标,string类型除外。

咱俩会意识,线程又尚未已毕联机了!lock(this)对于那种场地是丰裕的!所以必要我们对代码举行修改!修改后的代码如下: 

2、lock推荐的做法是运用静态的、只读的、私有的目的。

澳门葡京官方网站 83澳门葡京官方网站 84

3、保险lock的靶子在外部不可以修改才有意义,尽管lock的目的在外表改变了,对其它线程就会通行,失去了lock的意义。

private static object obj = new object();
        static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

*     不恐怕锁定字符串,锁定字符串尤其危险,因为字符串被集体语言运行库
(CLR)“暂留”。
那表示任何程序中任何给定字符串都唯有一个实例,就是那同一个指标表示了所有运行的行使程序域的兼具线程中的该公文。因而,只要在应用程序进度中的任何地方处拥有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。平日,最好幸免锁定
public
类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则
lock(this)
可能会有难点,因为不受控制的代码也只怕会锁定该目标。这或者引致死锁,即八个或更八个线程等待释放同一对象。出于同样的案由,锁定公共数据类型(比较于对象)也大概引致问题。而且lock(this)只对现阶段目标有效,如若八个对象时期就达不到一块的意义。lock(typeof(Class))与锁定字符串一样,范围太广了。*

View Code

  3.1 使用Monitor类完结线程同步      

由此翻看执行结果。会发觉代码完毕了大家的须求,五个线程按梯次执行了。那么 lock(this)
和lock(Obj)有何分裂吗? 大家再看一个示范代码:

     
Lock关键字是Monitor的一种替换用法,lock在IL代码中会被翻译成Monitor. 

static void Main(string[] args)
        {
            Class1 pro1 = new Class1();
            Class1 pro2 = new Class1();
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }

//另外新建一个类
 public class Class1
    {

        private static object obj = new object();

        public void ThreadMethod(object parameter)
        {
            lock (obj)   // 也可以使用 lock (typeof(Class1)) 方法来锁定
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }
    }

     lock(obj)

 

              {
                 //代码段
             } 
    就相同 
    Monitor.Enter(obj); 
                //代码段
    Monitor.Exit(obj);  

澳门葡京官方网站 85😉

           Monitor的常用属性和办法:

lock(this) 锁定 当前实例对象,如果有多个类实例的话,lock锁定的只是当前类实例,对其它类实例无影响。所有不推荐使用。 
lock(typeof(Model))锁定的是model类的所有实例。 这里的Model是指某个类名。
lock(obj)锁定的对象是全局的私有化静态变量。外部无法对该变量进行访问。 
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 
所以,lock的结果好不好,还是关键看锁的谁,如果外边能对这个谁进行修改,lock就失去了作用。
所以,一般情况下,使用私有的、静态的并且是只读的对象。

    Enter(Object) 在指定对象上赢得排他锁。

澳门葡京官方网站 86😉

    Exit(Object) 释放指定对象上的排他锁。 

总结:

 

1、lock的是必须是引用类型的靶子,string类型除外。

    Pulse 文告等待队列中的线程锁定目的处境的改变。

2、lock推荐的做法是应用静态的、只读的、私有的对象。

    PulseAll 布告所有的等候线程对象景况的改观。

3、保险lock的目的在外部不大概修改才有含义,借使lock的对象在表面改变了,对其他线程就会通行,失去了lock的意思。

    TryEnter(Object) 试图获取指定对象的排他锁。

     不能锁定字符串,锁定字符串特别危险,因为字符串被集体语言运行库
(CLR)“暂留”。
那象征任何程序中其余给定字符串都只有一个实例,就是那同一个目标表示了具有运行的使用程序域的有所线程中的该公文。由此,只要在应用程序进度中的任何岗位处拥有同样内容的字符串上放置了锁,就将锁定应用程序中该字符串的拥有实例。经常,最好防止锁定
public
类型或锁定不受应用程序lock块内决定的目的实例。例如,假如该实例可以被公开访问,则
lock(this)
只怕会有标题,因为不受控制的代码也恐怕会锁定该目的。那说不定造成死锁,即三个或更七个线程等待释放同一对象。出于同样的原由,锁定公共数据类型(相比较于对象)也说不定造成难题。而且lock(this)只对当下目的有效,如果多少个对象时期就达不到一块的机能。lock(typeof(Class))与锁定字符串一样,锁定的对象的效用域的限定太广了。

    TryEnter(Object,
Boolean)
 尝试拿到指定对象上的排他锁,并活动安装一个值,提示是或不是拿到了该锁。

3.1
使用Monitor类落成线程同步 
     

    Wait(Object) 释放对象上的锁并阻止当前线程,直到它再也拿到该锁。

     
Lock关键字是Monitor的一种替换用法,lock在IL代码中会被翻译成Monitor. 

     
常用的办法有多个,Monitor.Enter(object)方法是赢得锁,Monitor.Exit(object)方法是释放锁,那就是Monitor最常用的八个办法,在行使过程中为了幸免获取锁之后因为格外,致锁不可以自由,所以须要在try{}
catch(){}之后的finally{}结构体中释放锁(Monitor.Exit())。

     lock(obj)

Enter(Object)的用法很简短,看代码 

              {
                 //代码段
             } 
    就一律 
    Monitor.Enter(obj); 
                //代码段
    Monitor.Exit(obj);  

澳门葡京官方网站 87

           Monitor的常用属性和艺术:

     static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            Monitor.Enter(obj);      //Monitor.Enter(obj)  锁定对象
            try
            {
                for (int i = 0; i < 500; i++)
                {
                    Console.Write(Thread.CurrentThread.Name); 
                }
            }
            catch(Exception ex){   }
            finally
            { 
                Monitor.Exit(obj);  //释放对象
            } 
        } 

    Enter(Object) 在指定对象上取得排他锁。

澳门葡京官方网站 88

    Exit(Object) 释放指定对象上的排他锁。 

 

 

TryEnter(Object)TryEnter() 方法在品味拿到一个目的上的显式锁方面和
Enter()
方法类似。但是,它不像Enter()方法那样会堵塞执行。如果线程成功跻身关键区域那么TryEnter()方法会重临true. 和总结拿走指定对象的排他锁。看下边代码演示:

    Pulse 通告等待队列中的线程锁定目标景况的改动。

      我们得以通过Monitor.TryEnter(monster,
1000),该办法也能够避免死锁的发出,大家上面的事例用到的是该措施的重载,Monitor.TryEnter(Object,Int32),。 

    PulseAll 文告所有的等候线程对象意况的更改。

澳门葡京官方网站 89

    TryEnter(Object) 试图获取指定对象的排他锁。

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            bool flag = Monitor.TryEnter(obj, 1000);   //设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
        //上面的代码设置了锁定超时时间为1秒,也就是说,在1秒中后,
       //lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
            try
            {
                if (flag)
                {
                    for (int i = 0; i < 500; i++)
                    {
                        Console.Write(Thread.CurrentThread.Name); 
                    }
                }
            }
            catch(Exception ex)
            {

            }
            finally
            {
                if (flag)
                    Monitor.Exit(obj);
            } 
        } 

    TryEnter(Object, Boolean)
尝试拿到指定对象上的排他锁,并机关安装一个值,指示是不是拿走了该锁。

澳门葡京官方网站 90

    Wait(Object)
释放对象上的锁并阻止当前线程,直到它再度拿到该锁。

 Monitor.Wait和Monitor()Pause()

     
常用的艺术有七个,Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的八个格局,在利用进程中为了避免获取锁之后因为格外,致锁无法自由,所以必要在try{}
catch(){}之后的finally{}结构体中释放锁(Monitor.Exit())。

Wait(object)方法:释放对象上的锁并阻止当前线程,直到它再也取得该锁,该线程进入等待队列。
 Pulse方法:唯有锁的近日主人可以行使 Pulse 向等待对象发出信号,当前颇具指定对象上的锁的线程调用此格局以便向队列中的下一个线程发出锁的信号。接收到脉冲后,等待线程就被活动到就绪队列中。在调用 Pulse 的线程释放锁后,就绪队列中的下一个线程(不自然是收取到脉冲的线程)将获得该锁。
另外

Enter(Object)的用法很粗略,看代码 

        Wait 和 Pulse 方法必须写在 Monitor.Enter
和Moniter.Exit 之间。

澳门葡京官方网站 91😉

上面是MSDN的解释。不知道看代码:

     static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            Monitor.Enter(obj);      //Monitor.Enter(obj)  锁定对象
            try
            {
                for (int i = 0; i < 500; i++)
                {
                    Console.Write(Thread.CurrentThread.Name); 
                }
            }
            catch(Exception ex){   }
            finally
            { 
                Monitor.Exit(obj);  //释放对象
            } 
        } 

 首先大家定义一个攻击类,

澳门葡京官方网站 92😉

澳门葡京官方网站 93

 

/// <summary>
    /// 怪物类
    /// </summary>
    internal class Monster
    {
        public int Blood { get; set; }
        public Monster(int blood)
        {
            this.Blood = blood;
            Console.WriteLine("我是怪物,我有{0}滴血",blood);
        }
    }

TryEnter(Object)TryEnter()
方法在尝试得到一个目的上的显式锁方面和 Enter()
方法类似。不过,它不像Enter()方法那样会堵塞执行。倘使线程成功跻身关键区域那么TryEnter()方法会重临true. 和总结拿走指定对象的排他锁。看下面代码演示:

澳门葡京官方网站 94

      大家得以经过Monitor.TryEnter(monster,
1000),该措施也可以避免死锁的爆发,我们上边的例证用到的是该格局的重载,Monitor.TryEnter(Object,Int32),。 

然后在概念一个攻击类

澳门葡京官方网站 95😉

澳门葡京官方网站 96

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            bool flag = Monitor.TryEnter(obj, 1000);   //设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
        //上面的代码设置了锁定超时时间为1秒,也就是说,在1秒中后,
       //lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
            try
            {
                if (flag)
                {
                    for (int i = 0; i < 500; i++)
                    {
                        Console.Write(Thread.CurrentThread.Name); 
                    }
                }
            }
            catch(Exception ex)
            {

            }
            finally
            {
                if (flag)
                    Monitor.Exit(obj);
            } 
        } 
/// <summary>
    /// 攻击类
    /// </summary>
    internal class Play
    {
        /// <summary>
        /// 攻击者名字
        /// </summary>
        public string Name { get; set; } 
        /// <summary>
        /// 攻击力
        /// </summary>
        public int Power{ get; set; }
        /// <summary>
        /// 法术攻击
        /// </summary>
        public void magicExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood>0)
            {
                Monitor.Wait(monster);
                Console.WriteLine("当前英雄:{0},正在使用法术攻击打击怪物", this.Name);
                if(m.Blood>= Power)
                {
                    m.Blood -= Power;
                }
                else
                {
                    m.Blood = 0;
                }
                Thread.Sleep(300);
                Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                Monitor.PulseAll(monster);
            }
            Monitor.Exit(monster);
        }
        /// <summary>
        /// 物理攻击
        /// </summary>
        /// <param name="monster"></param>
        public void physicsExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood > 0)
            {
                Monitor.PulseAll(monster);
                if (Monitor.Wait(monster, 1000))     //非常关键的一句代码
                {
                    Console.WriteLine("当前英雄:{0},正在使用物理攻击打击怪物", this.Name);
                    if (m.Blood >= Power)
                    {
                        m.Blood -= Power;
                    }
                    else
                    {
                        m.Blood = 0;
                    }
                    Thread.Sleep(300);
                    Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                }
            }
            Monitor.Exit(monster);
        }
    }

澳门葡京官方网站 97😉

澳门葡京官方网站 98

 Monitor.Wait和Monitor()Pause()

实施代码:

Wait(object)方法:释放对象上的锁并阻止当前线程,直到它再度取得该锁,该线程进入等待队列。
 Pulse方法:只有锁的当前主人可以选用 Pulse 向等待对象发出信号,当前享有指定对象上的锁的线程调用此办法以便向队列中的下一个线程发出锁的信号。接收到脉冲后,等待线程就被移动到就绪队列中。在调用 Pulse 的线程释放锁后,就绪队列中的下一个线程(不自然是接受到脉冲的线程)将收获该锁。
另外

澳门葡京官方网站 99

        Wait
和 Pulse 方法必须写在 Monitor.Enter 和Moniter.Exit
之间**
。**

    static void Main(string[] args)
        {
            //怪物类
            Monster monster = new Monster(1000);
            //物理攻击类
            Play play1 = new Play() { Name = "无敌剑圣", Power = 100 };
            //魔法攻击类
            Play play2 = new Play() { Name = "流浪法师", Power = 120 };
            Thread thread_first = new Thread(play1.physicsExecute);    //物理攻击线程
            Thread thread_second = new Thread(play2.magicExecute);     //魔法攻击线程
            thread_first.Start(monster);
            thread_second.Start(monster);
            Console.ReadKey();
        }

地方是MSDN的诠释。不了然看代码:

澳门葡京官方网站 100

 首先我们定义一个怪物类,被攻击类,

输出结果:

澳门葡京官方网站 101😉

澳门葡京官方网站 102

/// <summary>
    /// 怪物类
    /// </summary>
    internal class Monster
    {
        public int Blood { get; set; }
        public Monster(int blood)
        {
            this.Blood = blood;
            Console.WriteLine("我是怪物,我有{0}滴血",blood);
        }
    }

总结:

澳门葡京官方网站 103😉

  先是种情状:

接下来在概念一个玩家类,攻击类

  1. thread_first首先取得同步对象的锁,当执行到 Monitor.Wait(monster);时,thread_first线程释放自身对一头对象的锁,流放本人到等候队列,直到本身再次得到锁,否则一直不通。
  2. 而thread_second线程一先河就竞争同步锁所以处于就绪队列中,这时候thread_second间接从稳妥队列出来拿到了monster对象锁,起头实施到Monitor.PulseAll(monster)时,发送了个Pulse信号。
  3. 这时候thread_first接收到信号进入到妥善状态。然后thread_second继续往下举办到
    Monitor.Wait(monster,
    1000)时,那是一句相当主要的代码,thread_second将本身放逐到等候队列并释放自个儿对同步锁的占据,该等待安装了1S的超时值,当B线程在1S以内没有重新得到到锁自动添加到就绪队列。
  4. 这时thread_first从Monitor.Wait(monster)的梗塞截至,再次回到true。起始实施、打印。执行下一行的Monitor.Pulse(monster),那时候thread_second假使1S的时间还没过,thread_second接收到信号,于是将协调添加到就绪队列。
  5. thread_first的一道代码块截止之后,thread_second再度拿到执行权, Monitor.Wait(m_smplQueue,
    1000)重返true,于是连续从该代码处往下举行、打印。当再一次实施到Monitor.Wait(monster,
    1000),又起来了手续3。
  6. 逐条循环。。。。

澳门葡京官方网站 104😉

 
 其次种意况:thread_second首先得到同步锁对象,首先实施到Monitor.PulseAll(monster),因为程序中向来不索要拭目以待信号进入就绪状态的线程,所以这一句代码没有意义,当执行到 Monitor.Wait(monster,
1000),自动将协调放逐到等候队列并在这边阻塞,1S
时间之后thread_second自动添加到就绪队列,线程thread_first得到monster对象锁,执行到Monitor.Wait(monster);时发出堵塞释放同步对象锁,线程thread_second执行,执行Monitor.PulseAll(monster)时通知thread_first。于是又开始首先种情形…

/// <summary>
    /// 玩家类
    /// </summary>
    internal class Play
    {
        /// <summary>
        /// 攻击者名字
        /// </summary>
        public string Name { get; set; } 
        /// <summary>
        /// 攻击力
        /// </summary>
        public int Power{ get; set; }
        /// <summary>
        /// 法术攻击
        /// </summary>
        public void magicExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood>0)
            {
                Monitor.Wait(monster);
                Console.WriteLine("当前英雄:{0},正在使用法术攻击打击怪物", this.Name);
                if(m.Blood>= Power)
                {
                    m.Blood -= Power;
                }
                else
                {
                    m.Blood = 0;
                }
                Thread.Sleep(300);
                Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                Monitor.PulseAll(monster);
            }
            Monitor.Exit(monster);
        }
        /// <summary>
        /// 物理攻击
        /// </summary>
        /// <param name="monster"></param>
        public void physicsExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood > 0)
            {
                Monitor.PulseAll(monster);
                if (Monitor.Wait(monster, 1000))     //非常关键的一句代码
                {
                    Console.WriteLine("当前英雄:{0},正在使用物理攻击打击怪物", this.Name);
                    if (m.Blood >= Power)
                    {
                        m.Blood -= Power;
                    }
                    else
                    {
                        m.Blood = 0;
                    }
                    Thread.Sleep(300);
                    Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                }
            }
            Monitor.Exit(monster);
        }
    }

Monitor.Wait是让眼下进度睡眠在临界资源上并释放独占锁,它只是等待,并不脱离,当等待甘休,就要继续执行剩下的代码。

澳门葡京官方网站 105😉

 

举办代码:

  3.0 使用Mutex类实现线程同步

澳门葡京官方网站 106😉

   
  Mutex的凸起特征是足以跨应用程序域边界对资源开展垄断访问,即可以用于共同分裂进度中的线程,那种意义自然那是以捐躯更加多的系统资源为代价的。

    static void Main(string[] args)
        {
            //怪物类
            Monster monster = new Monster(1000);
            //物理攻击类
            Play play1 = new Play() { Name = "无敌剑圣", Power = 100 };
            //魔法攻击类
            Play play2 = new Play() { Name = "流浪法师", Power = 120 };
            Thread thread_first = new Thread(play1.physicsExecute);    //物理攻击线程
            Thread thread_second = new Thread(play2.magicExecute);     //魔法攻击线程
            thread_first.Start(monster);
            thread_second.Start(monster);
            Console.ReadKey();
        }

  首要常用的多个法子:

澳门葡京官方网站 107😉

 public virtual bool WaitOne()   阻止当前线程,直到近年来System.Threading.WaitHandle 收到信号获取互斥锁。

输出结果:

 public void ReleaseMutex()     释放 System.Threading.Mutex 一次。

澳门葡京官方网站 108

  使用实例:

总结:

澳门葡京官方网站 109

  率先种情况:

    static void Main(string[] args)
        {
            Thread[] thread = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                thread[i] = new Thread(ThreadMethod1);
                thread[i].Name = i.ToString();
            }
            for (int i = 0; i < 3; i++)
            {
                thread[i].Start();
            }
            Console.ReadKey(); 
        } 

        public static void ThreadMethod1(object val)
        {
            mutet.WaitOne();    //获取锁
            for (int i = 0; i < 500; i++)
            {
                Console.Write(Thread.CurrentThread.Name); 
            } 
            mutet.ReleaseMutex();  //释放锁
        }
  1. thread_first首先拿到同步对象的锁,当执行到 Monitor.Wait(monster);时,thread_first线程释放本身对一头对象的锁,流放本人到等候队列,直到本身重新拿到锁,否则一贯不通。
  2. 而thread_second线程一初始就竞争同步锁所以处于就绪队列中,这时候thread_second直接从稳妥队列出来得到了monster对象锁,开端执行到Monitor.PulseAll(monster)时,发送了个Pulse信号。
  3. 这时候thread_first接收到信号进入到妥善状态。然后thread_second继续往下实施到
    Monitor.Wait(monster, 1000)时,那是一句卓殊关键的代码,thread_second将团结放逐到等候队列并释放自我对同步锁的独占,该等待安装了1S的超时值,当B线程在1S之内没有再次获拿到锁自动添加到就绪队列。
  4. 这时thread_first从Monitor.Wait(monster)的不通为止,再次来到true。开始履行、打印。执行下一行的Monitor.Pulse(monster),那时候thread_second借使1S的小时还没过,thread_second接收到信号,于是将团结添加到就绪队列。
  5. thread_first的联合代码块甘休之后,thread_second再度赢得执行权, Monitor.Wait(m_smplQueue,
    1000)重返true,于是接二连三从该代码处往下举行、打印。当再次实施到Monitor.Wait(monster,
    1000),又起来了手续3。
  6. 次第循环。。。。

澳门葡京官方网站 110

   其次种情况:thread_second首先得到同步锁对象,首先实施到Monitor.PulseAll(monster),因为程序中尚无索要拭目以待信号进入就绪状态的线程,所以这一句代码没有意思,当执行到 Monitor.Wait(monster,
1000),自动将协调放逐到等候队列并在此地阻塞,1S 时间过后thread_second自动添加到就绪队列,线程thread_first拿到monster对象锁,执行到Monitor.Wait(monster);时暴发短路释放同步对象锁,线程thread_second执行,执行Monitor.PulseAll(monster)时通知thread_first。于是又起来率先种情形…

 2、线程池

Monitor.Wait是让目前进程睡眠在临界资源上并释放独占锁,它只是等待,并不脱离,当等待截止,就要继续执行剩下的代码。

   
  下边介绍了介绍了平日利用的一大半的三三十二线程的例证,但在实质上开发中拔取的线程往往是大度的和越来越复杂的,那时,每趟都创立线程、启动线程。从品质上来讲,那样做并不佳好(因为每使用一个线程就要创设一个,须求占用系统开发);从操作上来讲,每趟都要开动,比较费心。为此引入的线程池的概念。

 

  好处:

  3.0
使用Mutex类实现
线程同步

  1.滑坡在开创和销毁线程上所花的日子以及系统资源的开支 
 
2.如不使用线程池,有只怕导致系统创建大气线程而致使消耗完系统内存以及”过度切换”。

   
  Mutex的凸起特色是足以跨应用程序域边界对资源开展垄断访问,即可以用于共同差距进程中的线程,那种效果本来那是以捐躯更多的系统资源为代价的。

在如何动静下使用线程池? 

  紧要常用的多个点子:

    1.单个义务处理的年月比较短 
    2.亟待处理的义务的数目大 

 public virtual bool WaitOne()
  阻止当前线程,直到近来 System.Threading.WaitHandle
收到信号获取互斥锁。

线程池最多管理线程数量=“处理器数 *
250”。相当于说,如若您的机械为2个2核CPU,那么CLR线程池的容量暗中同意上限便是1000

 public void ReleaseMutex()  
  释放 System.Threading.Mutex 一次。

经过线程池创制的线程暗许为后台线程,优先级暗中同意为诺玛l。

  使用实例:

代码示例:

澳门葡京官方网站 111😉

澳门葡京官方网站 112

    static void Main(string[] args)
        {
            Thread[] thread = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                thread[i] = new Thread(ThreadMethod1);
                thread[i].Name = i.ToString();
            }
            for (int i = 0; i < 3; i++)
            {
                thread[i].Start();
            }
            Console.ReadKey(); 
        } 

        public static void ThreadMethod1(object val)
        {
            mutet.WaitOne();    //获取锁
            for (int i = 0; i < 500; i++)
            {
                Console.Write(Thread.CurrentThread.Name); 
            } 
            mutet.ReleaseMutex();  //释放锁
        }
    static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod1), new object());    //参数可选
            Console.ReadKey();
        }

        public static void ThreadMethod1(object val)
        { 
            for (int i = 0; i <= 500000000; i++)
            {
                if (i % 1000000 == 0)
                {
                    Console.Write(Thread.CurrentThread.Name);
                } 
            } 
        }

澳门葡京官方网站 113😉

澳门葡京官方网站 114

 2、线程池

 

   
  上边介绍了介绍了经常使用的多数的二十四线程的事例,但在骨子里支出中运用的线程往往是大量的和进一步复杂的,那时,每一次都创制线程、启动线程。从性质上来讲,这样做并不出色(因为每使用一个线程就要创设一个,需求占用系统开发);从操作上来讲,每趟都要开动,相比较麻烦。为此引入的线程池的概念。

 

  好处:

有关线程池的诠释请参考:

  1.减去在创设和销毁线程上所花的时日以及系统资源的费用 
 
2.如不使用线程池,有只怕导致系统创建大气线程而招致消耗完系统内存以及”过度切换”。

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html

在哪些情状下使用线程池? 

    1.单个职分处理的时刻比较短 
    2.急需处理的天职的多少大 

线程池最多管理线程数量=“处理器数 *
250”。也等于说,就算你的机器为2个2核CPU,那么CLR线程池的容量暗许上限便是1000

通过线程池创造的线程专擅认同为后台线程,优先级暗许为Normal。

代码示例:

澳门葡京官方网站 115😉

    static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod1), new object());    //参数可选
            Console.ReadKey();
        }

        public static void ThreadMethod1(object val)
        { 
            for (int i = 0; i <= 500000000; i++)
            {
                if (i % 1000000 == 0)
                {
                    Console.Write(Thread.CurrentThread.Name);
                } 
            } 
        }

澳门葡京官方网站 116😉

 

 

关于线程池的解释请参见:

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html

 

======

相关文章