线程

需要掌握的有:

1,线程的概念

2,线程的调度

3,线程也分前后台

4,线程的容器,线程池

5,线程同步

===============================================================================================

一:进程的概念: 进程是一个可执行程序,由虚拟空间地址,数据,代码,其他操作系统资源组成,一个应用程序可以有一个或多个进程.

线程的概念:线程是进程的独立执行单元,是CPU调度和分派的基本单位,一个进程可以有一个或多个线程,其中一个线程是主线程

 

================================================================================================

二:基于Windows是抢占式多线程操作系统,线程会在任意时间里被抢占,来调度另一个线程

class Program
    {
      
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始执行");
            Thread t1 = new Thread(new ThreadStart(Work1));
            Thread t2 = new Thread(new ThreadStart(Work1));
            t1.Start();
            t2.Start();
            Console.WriteLine("主线程执行结束");
        }

        public static void Work1()
        { 
            while(true)
            {
                Thread.Sleep(100);
                Console.WriteLine("线程ID = {0}在执行",Thread.CurrentThread.ManagedThreadId.ToString());
            }
        }

        public static void Work2()
        { 
            while(true)
            {
                Thread.Sleep(100);
                Console.WriteLine("线程ID = {0}在执行",Thread.CurrentThread.ManagedThreadId.ToString());
            }
        
        }

    }

 

对于线程调度的问题,我们可以通过设置线程的优先级,来让指定的线程优先执行

通过设置Priority属性来设置,有5个优先级,

ThreadPriority.xxx   这是个枚举,F12进去能看到顺序,从0到4,优先级依次递增

 

 

===============================================================================================

三:Thread 类创建的线程,默认是前台线程,主线程是前台线程,并且所有的前台线程执行完毕,后台线程就会被CLR强制结束,并且不会抛出异常,如下代码所以,

后台线程并没有被执行,因为前台线程已经结束

有三种方法可以让后台线程执行完

1:让前台线程Thread.Sleep();

2,把后台线程变成前台线程,通过IsBackgroud属性来设置

3,通过join()方法,让后台线程先执行完毕

 1   static void Main(string[] args)
 2         {
 3             Console.WriteLine("主线程开始,ID={0}",Thread.CurrentThread.ManagedThreadId.ToString());
 4 
 5             Thread td = new Thread(new ThreadStart(Work));
 6             td.IsBackground = true;
 7             td.Start();
 8             Console.WriteLine("主线程结束,ID={0}", Thread.CurrentThread.ManagedThreadId.ToString());
 9         }
10 
11         public static void Work()
12         {
13             Console.WriteLine("后台线程开始,ID={0}",Thread.CurrentThread.ManagedThreadId.ToString());
14             for (int i = 0; i < 10;i++ ) 
15             {
16                 Console.WriteLine("后台线程在工作,ID={0}",Thread.CurrentThread.ManagedThreadId.ToString());
17             }
18             Console.WriteLine("后台工作线程结束,ID={0}",Thread.CurrentThread.ManagedThreadId.ToString());
19         }

四 :线程池

通过手动创建线程,在销毁和创建的过程中会占用一定的资源,造成性能的损失,这个时候我们可以用线程池

线程池可以理解为线程的集合,当有任务要执行时,会通过 QueueUserWorkItem(WaitCallback callBack);将任务添加到请求消息队列中,线程池实现的代码会从消息队列中

提取任务,并委派给线程池中的线程去执行,执行完毕后,线程会被释放,但是不会被销毁,释放后等待下次任务的执行,如果线程池的线程不够使用就会创建新的线程,去执行任务

 

线程池的线程为后台线程,并且优先级默认为Normal

 1 class Program
 2     {
 3       
 4         static void Main(string[] args)
 5         {
 6             Console.WriteLine("主线程开始");
 7             ThreadPool.QueueUserWorkItem(Work);
 8             ThreadPool.QueueUserWorkItem(Work,"hello");
 9             Thread.Sleep(3000);
10             Console.WriteLine("主线程结束");
11         }
12 
13         public static void Work(Object o)
14         {
15             Console.WriteLine("工作线程开始");
16             if (o == null)
17             { 
18                 Console.WriteLine("工作线程 ID={0}",Thread.CurrentThread.ManagedThreadId.ToString());
19             }
20             else
21             {
22                 Console.WriteLine("工作线程ID = {0},参数为{1}",Thread.CurrentThread.ManagedThreadId.ToString(),o.ToString());
23 
24             }
25             
26         }
27 
28         
29 
30       
31 
32     }

取消线程池线程,CancellationTokenSource的 Cancel()方法可以取消线程池的线程,取消后,CancellationToke 的IsCancellationRequested的属性为true

 1  class Program
 2     {
 3       
 4         static void Main(string[] args)
 5         {
 6             Console.WriteLine("主线程开始");
 7             CancellationTokenSource cts = new CancellationTokenSource();
 8             ThreadPool.QueueUserWorkItem(Work,cts.Token);
 9             Console.WriteLine("按回车取消");
10             Console.ReadKey();
11             cts.Cancel();
12             Console.ReadKey();
13             Console.WriteLine("主线程结束");
14         }
15 
16         public static void Work(Object o)
17         {
18             CancellationToken token = (CancellationToken)o;
19             for (int i = 0; i < 100;i++ )
20             {
21                 Thread.Sleep(300);
22                 Console.WriteLine(i);
23                 if(token.IsCancellationRequested)
24                 {
25                     Console.WriteLine("计数取消");
26                     return;
27                 }
28 
29             }
30             
31         }
32 
33         
34 
35       
36 
37     }

五,多个线程共同操作同一个资源,为了保证不损坏资源的数据,确保某一时刻只有一个线程在操作共享资源

 1  class Program
 2     {
 3         public static int tickets = 100;
 4         static void Main(string[] args)
 5         {
 6             Console.WriteLine("主线程开始");
 7             ThreadPool.QueueUserWorkItem(MaiPiao1);
 8             ThreadPool.QueueUserWorkItem(MaiPiao2);
 9             Thread.Sleep(20000);
10             Console.WriteLine("主线程结束");
11         }
12 
13         public static void MaiPiao1(object o)
14         { 
15             while(true)
16             {
17                 Thread.Sleep(300);
18                 Console.WriteLine("窗口1----剩余票{0}",tickets);
19                 tickets--;
20                 if (tickets <= 0) break;
21             }
22         }
23 
24         public static void MaiPiao2(object o)
25         {
26             while (true)
27             {
28                 Thread.Sleep(300);
29                 Console.WriteLine("窗口2----剩余票{0}", tickets);
30                 tickets--;
31                 if (tickets <= 0) break;
32             }
33         }
34 
35 
36     }

上面的代码证实了,多线程在操作共同的资源的时候,会造成资源数据的损坏

此时可以通过使用Monitor来实现线程同步

 1     public static void MaiPiao1(object o)
 2         { 
 3             while(true)
 4             {
 5                 try
 6                 {
 7                     Thread.Sleep(300);
 8                     Monitor.Enter(mykey);
 9                     Console.WriteLine("窗口1----剩余票{0}", tickets);
10                     tickets--;
11                     if (tickets <= 0) break;
12                 }
13                 finally
14                 {
15                     Monitor.Exit(mykey);
16                 }
17               
18             }
19         }

关于死锁,线程1和线程2都使用同一个锁,线程1没有释放锁,那么线程1和线程2都处于等待状态

 

posted @ 2016-09-27 10:43  高手坟墓灬  阅读(138)  评论(0编辑  收藏  举报