线程基础--读多线程编程实战—(2)

1.线程优先级

通过过设置属性Priority

        class ThreadSample
        {
            private bool _isStop = false;
            public void Stop()
            {
                _isStop = true;
            }
            public void CountNumbers()
            {
                long counter = 0;
                while(!_isStop)
                {
                    counter++;
                }
                Console.WriteLine($"{Thread.CurrentThread.Name} with {Thread.CurrentThread.Priority,11} "+
                    $"priority has a count:{counter,13:N0}");
            }
        }

        static void RunThreads()
        {
            var sample = new ThreadSample();
            var oneTh = new Thread(sample.CountNumbers);
            oneTh.Name = "thread one";

            var twoTh = new Thread(sample.CountNumbers);
            twoTh.Name = "thread two";

            oneTh.Priority = ThreadPriority.Highest;//最高优先级
            twoTh.Priority = ThreadPriority.Lowest;//最低优先级

            oneTh.Start();
            twoTh.Start();

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

 

            //线程优先级
            Console.WriteLine($"Current thread priority:{Thread.CurrentThread.Priority}");
            Console.WriteLine("Running on all cores available");
            RunThreads();
            Thread.Sleep(2000);

            Console.WriteLine( "Running on a single core");
            GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
            RunThreads();

输出:

使用计算机上的可用核,在2秒内得到初步结果,最高优先级的线程通常会计算更多的迭代,但是2个结果接近。

模拟在一个核上运行,结果完全不同了,CPU核大部分时间运行高优先级的线程,只留很少的时间运行低优先级的线程

2. 前台线程和后台线程

        class ThreadSample2
        {
            private readonly int _iterations;
            public ThreadSample2(int iteratios)
            {
                _iterations = iteratios;
            }

            public void CountNumbers()
            {
                for (int i = 0; i < _iterations; i++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
                }
            }
        }

 

            //前台线程和后台线程
            var foreSample = new ThreadSample2(10);
            var backSample= new ThreadSample2(20);

            var oneTh = new Thread(foreSample.CountNumbers);
            oneTh.Name = "Forground Thread";

            var twoTh = new Thread(backSample.CountNumbers);
            twoTh.Name = "Background Thread";
            twoTh.IsBackground = true;

            oneTh.Start();
            twoTh.Start();

输出:

通过设置属性 IsBackground来设置后台线程,默认显示创建的线程都是前台线程。进程会等待前台线程完成后再结束工作,但是如果只剩下后台进程则会直接结束工作。

 

3.向线程传递参数

        static void Count(object iterations)
        {
            CounterNmbers((int)iterations);
        }

        private static void CounterNmbers(int iterations)
        {
            for (int i = 0; i <=iterations; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
            }
        }

        static void PrintNumber(int number)
        {
            Console.WriteLine(number);
        }

        class Threadsample
        {
            private readonly int _iterations;
            public Threadsample(int iterations)
            {
                _iterations = iterations;
            }
            public void CountNumbers()
            {
                for (int i = 0; i <=_iterations; i++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine($"{Thread.CurrentThread.Name} print{i}");
                }
            }
        }
 

测试代码:

            var sample = new Threadsample(10);

            var t1 = new Thread(sample.CountNumbers);
            t1.Name = "Thread_1";
            t1.Start();
            t1.Join();

            Console.WriteLine("----------------------------");

//通过实例化类的构造函数传入参数值 10,创建新的线程,传入实例方法。

            var t2 = new Thread(Count);
            t2.Name = "Thread_2";
            t2.Start(8);
            t2.Join();
            Console.WriteLine("----------------------------");

//start( ) 方法接收一个object类型的单个参数,8传给Count对象,被转换为整形。

            var t3 = new Thread(() => CounterNmbers(12));
            t3.Name = "Thread_3";
            t3.Start();
            t3.Join();
            Console.WriteLine("----------------------------");

// 使用Lambda表达式,传递数字12,


            int i = 10;
            var t4 = new Thread(() => PrintNumber(i));
            i = 20;
            var t5 = new Thread(() => PrintNumber(i));
            t4.Start();
            t5.Start();

// lambda表达式中使用相同变量,共享变量,导致这个2个线程启动之前变量被修改为20

输出:

4. 使用Lock关键字

确保当一个线程使用某些资源时其它线程无法使用该资源。

        abstract class CounterBase
        {
            public abstract void Increment();
            public abstract void Decrement();
        }

        class Counter : CounterBase
        {
            public int Count { get; private set; }
            public override void Decrement()
            {
                Count--;
            }

            public override void Increment()
            {
                Count++;
            }
        }

        class CounterWithLock : CounterBase
        {
            private readonly object _syncRoot = new object();
            public int Count { get; private set; }
            public override void Decrement()
            {
                lock (_syncRoot)
                {
                    Count--;
                }
            }

            public override void Increment()
            {
                lock (_syncRoot)
                {
                    Count++;
                }
            }
        }

        static void TestCounter(CounterBase c)
        {
            for (int i = 0; i < 100000; i++)
            {
                c.Increment();
                c.Decrement();
            }

        }
测试代码:

            Console.WriteLine("Unlock......");
            var c = new Counter();

            var t1 = new Thread(() => TestCounter(c));
            var t2 = new Thread(() => TestCounter(c));
            var t3 = new Thread(() => TestCounter(c));

            t1.Start();
            t2.Start();
            t3.Start();

            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine($"Total count:{c.Count}");
            Console.WriteLine("=================================");
            //启动3个线程共享变量,导致结果不确定,可能是0但大多数情况不为0
            //Counter类不是线程安全的,存在竞争条件多线程环境中常见导致错误的原因

            Console.WriteLine("Lock......");
            var cl = new CounterWithLock();

            t1 = new Thread(() => TestCounter(cl));
            t2 = new Thread(() => TestCounter(cl));
            t3 = new Thread(() => TestCounter(cl));

            t1.Start();
            t2.Start();
            t3.Start();

            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine($"Total count:{cl.Count}");
            //lock关键字 锁定一个对象,需要访问该对象的其它线程则处于锁定状态,直到该对象解除

输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flysh05

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值