在学习ThreadStart时,做过2个线程的练习-输出奇数和偶数,每次结果不一样,说明这两个线程随机的交替进行。如果希望控制输出顺序,就要定义优先级。

在 C# 中线程的优先级使用线程的 Priority 属性设置即可,默认的优先级是 Normal

在设置优先级后,优先级高的线程将优先执行。但不能说优先级高的执行完毕才执行优先级低的。

优先级的值通过 ThreadPriority 枚举类型来设置,从低到高分别为LowestBelowNormalNormalAboveNormalHighest

对前一个练习做一下修改,设置每一个线程的优先级,控制执行顺序。

using System;
using System.Threading;
namespace Priority多线程优先级控制
{
      class Program
      {
            static void Main(string[] args)
            {
                  Console.WriteLine("Priority多线程优先级控制");
                  ThreadStart threadStart1 = new ThreadStart(showEven);
                  Thread thread1 = new Thread(threadStart1);
                  thread1.Priority = ThreadPriority.Normal;//定义线程优先级为普通                  ThreadStart threadStart2 = new ThreadStart(showOdd);
                  Thread thread2 = new Thread(threadStart2);
                  thread2.Priority = ThreadPriority.Highest;//定义线程优先级为最高                  thread1.Start();
                  thread2.Start();
            }
            public static void showEven()
            {
                  //Console.WriteLine("显示偶数");
                  for(int i=2;i<=100;i+=2)
                  {
                        Console.Write(i + " ");
                  }
            }
            public static void showOdd()
            {
                  //Console.WriteLine("显示奇数");
                  for (int i=1;i<=100;i+=2)
                  {
                        Console.Write(i + " ");
                  }
            }
      }
}

每次运行,输出结果不完全一样,优先级别高的获得的执行次数相对多一点,但也不知等优先级别高的执行完毕才执行优先级别低的。这样一来即使定义了优先级,输出结果的顺序还是不可控的。

线程状态控制的方法包括暂停线程 (Sleep)、中断线程 (Interrupt)、挂起线程 (Suspend)、唤醒线程 (Resume)、终止线程 (Abort)。

改造一下前面的代码,加入sleep,完整代码如下

using System;
using System.Threading;
namespace sleep暂停线程
{
      class Program
      {
            static void Main(string[] args)
            {
                  Console.WriteLine("sleep暂停线程");
                  ThreadStart threadStart1 = new ThreadStart(showEven);
                  Thread thread1 = new Thread(threadStart1);
                  ThreadStart threadStart2 = new ThreadStart(showOdd);
                  Thread thread2 = new Thread(threadStart2);                  thread1.Start();
                  thread2.Start();            }
            public static void showEven()
            {
                  for(int i=2;i<=100;i+=2)
                  {
                        Console.Write(i + " ");
                        Thread.Sleep(1000);//先输出,再暂停
                  }
            }
            public static void showOdd()
            {
                  for(int i=1;i<=100;i+=2)
                  {
                        Thread.Sleep(1000);
                        Console.Write(i + " ");
                  }
            }
      }
}

输出结果是

rxjava 多线程 优先级 多线程优先级设置_System

虽然交替输出,但是每次运行结果还是不完全一样,说明sleep不能完全控制输出的顺序。

下面练习一下线程终止Abort。模拟发红包,初始有10个,每次发一个,当数量少于5个,就停止发放。

完整代码如下

using System;
using System.Threading;
namespace Abort线程终止练习
{
      class Program
      {
            static void Main(string[] args)
            {
                  Console.WriteLine("Abort线程终止练习");
                  ThreadStart threadStart = new ThreadStart(RedEnvelop);
                  Thread thread = new Thread(threadStart);
                  thread.Start();
            }
            public static int count = 10;
            public static void RedEnvelop()
            {
                  //int count = 10;
                  try
                  {
                        while (count > 0)
                        {
                              count--;
                              if (count == 4)
                              {
                                    //终止进程
                                    Console.WriteLine("红包暂停发放");
                                    //Thread.Sleep(1000);
                                    Thread.CurrentThread.Abort();                              }
                              Console.WriteLine("还剩{0}个红包", count);
                        }
                  }
                  catch (ThreadAbortException ex)
                  {
                        // ThreadAbortException要在Exception的前面,因为Exception能够匹配所有异常
                        Console.WriteLine("Method1 ThreadAbortException: " + ex.ToString());
                  }
                  finally
                  {
                        Console.WriteLine("执行完毕!");
                  }            }
      }
}

目前,由于挂起线程 (Suspend) 和唤醒线程 (Resume) 的操作很容易造成线程的死锁状态,已经被弃用了,而是使用标识字段来设置线程挂起和唤醒的状态。

所谓线程死锁就是多个线程之间处于相互等待的状态。

线程分为前台线程后台线程,前台线程不用等主程序结束,后台线程则需要应用程序运行结束后才能结束。

此外,在应用程序运行结束后,后台线程即使没有运行完也会结束,前台线程必须等待自身线程运行结束后才会结束。

使用 Thread 对象的 IsBackground 属性来判断线程是否为后台线程。

还是做一个练习,对前一个项目程序判断是不是后台线程,如果不是,将其设置为后台线程

完整代码如下

using System;
using System.Threading;
namespace IsBackground是否为后台线程
{
      class Program
      {
            static void Main(string[] args)
            {
                  Console.WriteLine("IsBackground练习");
                  ThreadStart threadStart = new ThreadStart(RedEnvelop);
                  Thread thread = new Thread(threadStart);
                  thread.Start();
                  if(thread.IsBackground)
                  {
                        Console.WriteLine("是后台线程");
                  }
                  else
                  {
                        Console.WriteLine("不是后台线程");
                        thread.IsBackground = true;
                  }
            }
            public static int count = 10;
            public static void RedEnvelop()
            {
                  //int count = 10;
                  try
                  {
                        while (count > 0)
                        {
                              count--;
                              if (count == 4)
                              {
                                    //终止进程
                                    Console.WriteLine("红包暂停发放");
                                    //Thread.Sleep(1000);
                                    Thread.CurrentThread.Abort();                              }
                              Console.WriteLine("还剩{0}个红包", count);
                        }
                  }
                  catch (ThreadAbortException ex)
                  {
                        // ThreadAbortException要在Exception的前面,因为Exception能够匹配所有异常
                        Console.WriteLine("Method1 ThreadAbortException: " + ex.ToString());
                  }
                  finally
                  {
                        Console.WriteLine("执行完毕!");
                  }            }
      }
}