zoukankan      html  css  js  c++  java
  • 线程

    需要掌握的有:

    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都处于等待状态

  • 相关阅读:
    【CodeVS 1028】 花店橱窗布置
    超赞的网络流入门教程
    【BZOJ 1798】[Ahoi2009]Seq 维护序列seq
    【洛谷 1991】 无线通讯网
    【Poj 3469】 Dual Core CPU
    【BZOJ 3504 】[Cqoi2014]危桥
    【Poj 3436】 ACM Computer Factory
    【BZOJ 3990】 [SDOI2015]排序
    【COGS 1873】 [国家集训队2011]happiness(吴确)
    最小割PPt
  • 原文地址:https://www.cnblogs.com/sddz/p/5911928.html
Copyright © 2011-2022 走看看