多线程编程学习笔记-基础(二)

接上文 多线程编程学习笔记-基础(一)

五、终止线程 (Abort)

1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始");
            Thread t = new Thread(PrintNumberDely);

            //启动线程
            t.Start();
            Thread.Sleep(TimeSpan.FromSeconds(6));

            //线程终止
            t.Abort();          

            Console.WriteLine("线程终止");
            Console.WriteLine("启动新线程");
            t = new Thread(PrintNumber);
            t.Start();
            PrintNumber();
            Console.Read();          

        } 

        static void PrintNumber()
        {
            Console.WriteLine("第四个多线程程序开始。。。。Second:" + DateTime.Now.Second);
            for (int i = 0; i <10; i++)
            {
                Console.WriteLine(string.Format("{0}",i));
            }
        }

        /// <summary>
        /// 暂停2秒的方法
        /// </summary>
        static void PrintNumberDely()
        {
            Console.WriteLine("第一个多线程终止程序开始。。。。");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Second:{0} ==  {1}", DateTime.Now.Second, i));

                Thread.Sleep(TimeSpan.FromSeconds(2));            
          
            }
        }
    }
}

2.程序执行结果如下

 

 从结果中,可以看出来,程序先启动了子线程的打印数字方法,在运行了6秒之后,调用了abort方法,终止了子线程。但是这个abort是通过注入ThreadAbortException方法,从而使用线程终止,这种方法非常危险,不建议使用。在子线程终止之后,主线程继续运行。

 

六、检测线程状态(ThreadState)

1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始");
            Thread t = new Thread(PrintNumberStatus);
            Thread t2 = new Thread(DoNothing);
            //启动线程
            t2.Start();
            t.Start();
            //显示线程状态
            for (int i = 0; i < 10; i++)
            {

                Thread.Sleep(TimeSpan.FromMilliseconds(300));
                Console.WriteLine(t.ThreadState.ToString());
            }
            Thread.Sleep(TimeSpan.FromSeconds(4));
            //线程终止
            t.Abort();

            Console.WriteLine("线程终止");
            Console.WriteLine(string.Format("t线程状态:{0}", t.ThreadState.ToString()));
            Console.WriteLine(string.Format("t2线程状态:{0}", t2.ThreadState.ToString()));
            Console.Read();
        }
 

        static void DoNothing()
        {
            Console.WriteLine("第五个多线程程序开始。。。。Second:" + DateTime.Now.Second);
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }

        /// <summary>
        /// 暂停2秒的方法
        /// </summary>
        static void PrintNumberStatus()
        {
            Console.WriteLine("第五个多线程检测状态程序开始。。。。" + Thread.CurrentThread.ThreadState.ToString());
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Second:{0} ==  {1}", DateTime.Now.Second, i));
                Thread.Sleep(TimeSpan.FromSeconds(2)); 

            }
        }
    }
}

2.程序执行结果如下

 

 如上图,主线程启动时定义了两个子线程,一个会被终止,另一个会运行至结束。当我们启动了线程之后,t2线程的状态就会变成Running,然后会变成WaitSleepJoin,直到运行结束,变成Stopped。另一个t线程则会打印出数字来,当我们调用了abort方法之后,则t线程的状态就变成了AbortRequested。这充分说明了同步两个线程的复杂性,请不要程序中使用abort来终止线程。

 

七、线程优先级(Priority

1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics; 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始,当前线程的优先级:"+Thread.CurrentThread.Priority);
            Console.WriteLine("线程运行多核CPU上");
            //启动线程
            Run();  
            Thread.Sleep(TimeSpan.FromSeconds(2));
 

            //单核模拟
            Console.WriteLine("线程运行单核CPU上");     

            Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
            Run();
            Console.Read();

        }

 

        static void Run()
        {
            var demo = new ThreadRunDemo();
            Thread thread1 = new Thread(demo.CountNumber);
            thread1.Name = "ThreadOne";
            Thread thread2 = new Thread(demo.CountNumber);
            thread2.Name = "ThreadTwo";
            thread2.Priority = ThreadPriority.BelowNormal;
            Thread thread3 = new Thread(demo.CountNumber);
            thread3.Name = "ThreadThree";
 

            thread1.Priority = ThreadPriority.Highest;
            thread2.Priority = ThreadPriority.AboveNormal;
            thread3.Priority = ThreadPriority.Lowest; 

            thread1.Start();
            thread2.Start();
            thread3.Start();          

            Thread.Sleep(2000);
            demo.Stop();
        }
    }

    class ThreadRunDemo
    {
        private bool isStopped = false;
        public void Stop()
        {
            isStopped = true;
        }

        public void CountNumber()
        {
            long cnt = 0;
            while(!isStopped)
            {
                cnt++;
            }
            Console.WriteLine(string.Format("线程 {0} 的优先级 {1,11} ,一共计算了 {2,13} 数字",
Thread.CurrentThread.Name,Thread.CurrentThread.Priority.ToString(), cnt.ToString("N0"))); } } }

2.程序执行结果如下

 

 从上图的结果中,看出来当在多核CPU上运行多线程程序时,优先级所起到的作用区别不大,以上图的结果来看,最高优先级与最低优先级之间的差别在10%左右。如果在单核CPU上运行多线程程序时,优先级的作用的特别明显,以上图的结果来看,最高优先级与最低优先级之间的差别在100倍以上。

 

八、前台线程与后台线程

1.代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入线程
using System.Diagnostics; 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("开始,前台线程与后台线程");           

            var fore = new ThreadBackground(10);
            var back = new ThreadBackground(20);
            Thread threadF = new Thread(fore.CountNumber);
            threadF.Name = "前台线程";
            Thread threadB = new Thread(back.CountNumber);

            threadB.Name = "后台线程";
            threadB.IsBackground = true;
 

            //启动线程
            threadF.Start();
            threadB.Start();
            //Console.Read(); 

        }
    }

    class ThreadBackground
    {
        private  int cnt ;
        public  ThreadBackground(int count)
        {
            cnt = count;
        }

        public void CountNumber()
        {
            for (int i = 0; i < cnt; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine(string.Format("线程 {0} 打印 {1,11} 数字", Thread.CurrentThread.Name, i.ToString("N0")));
            }
            Console.WriteLine("{0} finished counting.",
                            Thread.CurrentThread.IsBackground ?
                            "Background Thread" : "Foreground Thread");        }
       
    }
}

 

2.程序执行结果

 

 根据上面的代码,当程序执行到如上图时,会一闪而过,退出。这是因为前台线程已经执行结束,虽然后台线程没有执行结束,但程序会自动终止后台线程。这就是前台线程与后台线程的区别,进程会等所有的前台线程执行完毕,如果此时只剩下后台线程没有执行完毕,则会直接结束工作。

 

posted @ 2017-10-20 13:35 DotNet菜园 阅读(...) 评论(...) 编辑 收藏