• 扎实基础_多线程


    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static SemaphoreSlim semLim = new SemaphoreSlim(3); //3表示最多只能有三个线程同时访问
            static void Main(string[] args)
            {
                //线程的意义,一个应用程序,如果有多个可执行部分,可以同时执行 如同时开启 多个线程进行爬虫
                //对于比较耗时的IO,数据库,或者WCF通信,可以单独开启后台线程执行,这样主线程就不会阻塞了,等执行完了,再通知主线程
    
                //知识点:线程同步,异步线程,循环线程, 跨线程访问
                #region 信号量(Semaphore)
                    for (int i = 0; i < 10; i++)
                    {
                        new Thread(SemaphoreTest).Start();
                    }
                    Console.Read();
                #endregion
    
                #region Taks线程
                    //1.new方式实例化一个Task任务,需要通过Start方式启动
                    Task task = new Task(() =>
                    {
                        Console.WriteLine($"hello");
                    });
                    task.Start();
    
                    //task.Factory.StartNew(Action action) 创建和启动一个Task任务
                    Task task1 = Task.Factory.StartNew(() =>
                    {
                        Console.WriteLine($"hello");
                    });
    
                    //task.Run(action action)
                    Task task2 = Task.Run(() =>
                    {
                        Thread.Sleep(100);
                        Console.WriteLine($"hello");
                    });
                #endregion
    
                #region Thread .net 4.0加入的
                    //通俗讲解Thread 一个人走路回家,突然想起老婆交代没有买盐, 正常情况 要么买完盐回家,要么回家之后再去买盐
                    //但是他学会一个Thread技能:于是Thread分身处一个自己去买盐 ,自己的主体边回家
                    //但是自己主体如果回到家了,Thread还没买到盐,那么也就不需要Thread了
    
                    Console.WriteLine("主线程开始");
                    //IsBackground=true,将其设置为后台线程
                    Thread t = new Thread(Run) { IsBackground = true };
                    t.Start();
                    Console.WriteLine("主线程在做其他的事!");
                    //主线程结束,后台线程会自动结束,不管有没有执行完成
                    //Thread.Sleep(300);
                    Thread.Sleep(1500);
                    Console.WriteLine("主线程结束");
    
                #endregion
    
                #region ThreadPoll
                    //通俗讲解ThreadPoll   走路回家,突然想起老婆交代没买 柴米油盐,姜醋茶 如果还是用Thread分身那么 买柴创建一个分身
                    //买米,买油,买盐,都需要创建 等创建好了,家也快到了,还是挨老婆打
                    //THreadPoll线程池,相当于你已经创建好了分身,需要买什么就叫一个分身去买,但是ThreadPoll也是有最大限制 比如10个
                    //如果超过了限制,那么就需要重新创建新的线程,如果10个 只需要7个去执行,其他就会被设置成空闲状态,7个执行完了也会被设置成空闲状态,而不会消失
    
    
                    ThreadPool.QueueUserWorkItem(m =>
                        {
                            Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
                        });
    
                #endregion
    
                #region MyRegion async/await  .NET 4.5 ,C# 5.0
    
                    //async用来修饰方法,表明这个方法是异步的,声明的方法的返回类型必须为:void,Task或Task < TResult >。
    
                    //await必须用来修饰Task或Task < TResult >,而且只能出现在已经用async关键字修饰的异步方法中。通常情况下,async / await成对出现才有意义,
                    Console.WriteLine("-------主线程启动-------");
                    Task<int> taskAsync = GetStrLengthAsync();
                    Console.WriteLine("主线程继续执行");
                    Console.WriteLine("Task返回的值" + taskAsync.Result);
                    Console.WriteLine("-------主线程结束-------");
    
    
                #endregion
    
                #region 线程同步 是指在某一时刻只有一个线程可以访问变量
                    // c#为同步访问变量提供了一个非常简单的方式,即使用c#语言的关键字Lock,它可以把一段代码定义为互斥段,
                    //互斥段在一个时刻内只允许一个线程进入执行,实际上是Monitor.Enter(obj),Monitor.Exit(obj)的语法糖。在c#中,lock的用法如下:
                    //lock (obj) { 需要执行的代码 }
    
                    BookShop book = new BookShop();
                    //创建两个线程同时访问Sale方法
                    Thread t1 = new Thread(book.Sale);
                    Thread t2 = new Thread(book.Sale);
                    //启动线程
                    t1.Start();
                    t2.Start();
                    Console.ReadKey();
                #endregion
    
                #region  跨线程访问
    
                #endregion
    
                #region 知识点 
                //1.利用Thread新建线程和调用Task都是用非主线程异步执行工作,主线程不等待,
                //  不同点是Task使用线程池线程,任务结束后线程不会销毁,资源开销相对于Thread新建线程相对小一点。
                //2.Task和直接Task.Run没有区别。
                //3.利用await只能调用有async声名的方法主线程在await处等待异步执行结果,
                //但是此时主线程不会被阻塞掉。(如果此时主线程不去处理其他的事情,
                //那么和Thread调用线程,对于使用者来说是没有区别的)
                #endregion
    
    
                #region 属性名称    说明
                //CurrentThread         获取当前正在运行的线程。
                //ExecutionContext      获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
                //IsBackground          bool,指示某个线程是否为后台线程。
                //IsThreadPoolThread    bool,指示线程是否属于托管线程池。
                //ManagedThreadId       int, 获取当前托管线程的唯一标识符。
                //Name                  string, 获取或设置线程的名称。
                //Priority              获取或设置一个值,该值指示线程的调度优先级 。 Lowest < BelowNormal < Normal < AboveNormal < Highest>
                //ThreadState 获取一个值,该值包含当前线程的状态。 Unstarted、Sleeping、Running 等
                #endregion
    
    
                #region   方法名称 说明
    
                //GetDomain()       返回当前线程正在其中运行的当前域。
                //GetDomainId()     返回当前线程正在其中运行的当前域Id。
                //Start()           执行本线程。(不一定立即执行,只是标记为可以执行)
                //Suspend()         挂起当前线程,如果当前线程已属于挂起状态则此不起作用
                //Resume()          继续运行已挂起的线程。
                //Interrupt()       中断处于 WaitSleepJoin 线程状态的线程。
                //Abort()           终结线程
                //Join()            阻塞调用线程,直到某个线程终止。
                //Sleep()            把正在运行的线程挂起一段时间。
                #endregion
    
    
            }
    
            /// <summary>
            /// Semaphore负责协调线程,可以限制对某一资源访问的线程数量
            /// </summary>
            static void SemaphoreTest()
            {
                semLim.Wait();
                Console.WriteLine("线程" + Thread.CurrentThread.ManagedThreadId.ToString() + "开始执行");
                Thread.Sleep(2000);
                Console.WriteLine("线程" + Thread.CurrentThread.ManagedThreadId.ToString() + "执行完毕");
                semLim.Release();
            }
    
            //用于 Thread
            static void Run()
            {
                Thread.Sleep(700);
                Console.WriteLine("这是后台线程调用");
            }
    
            //用于 async/await
            static async Task<int> GetStrLengthAsync()
            {
                Console.WriteLine("GetStrLengthAsync方法开始执行");
                //此处返回的<string>中的字符串类型,而不是Task<string>
                string str = await GetString();
                Console.WriteLine("GetStrLengthAsync方法执行结束");
                return str.Length;
            }
    
            //用于 async/await
            static Task<string> GetString()
            {
                //Console.WriteLine("GetString方法开始执行")
                return Task<string>.Run(() =>
                {
                    Thread.Sleep(2000);
                    return "GetString的返回值";
                });
            }
        }
    
        //用于线程同步
        class BookShop
        {
            //剩余图书数量
            public int num = 1;
            private static readonly object locker = new object();
            public void Sale()
            {
    
                lock (locker)
                {
                    int tmp = num;
                    if (tmp > 0)//判断是否有书,如果有就可以卖
                    {
                        Thread.Sleep(1000);
                        num -= 1;
                        Console.WriteLine("售出一本图书,还剩余{0}本", num);
                    }
                    else
                    {
                        Console.WriteLine("没有了");
                    }
                }
            }
        }
    
    }
  • 相关阅读:
    golang 二进制转十进制实现方式
    mysql select column default value if is null
    MySQL 忘记root密码解决方法,基于Ubuntu 14.10
    ecshop 修改记录20150710
    mac os x 10.9.3 升级到10.10.4 记录
    View requires API level 14 (current min is 8): <GridLayout>
    android开发过程中遇到的坑
    如何为网站设置站点图标
    seq 显示00 01的格式
    lvs realserver 配置VIP
  • 原文地址:https://www.cnblogs.com/LZXX/p/12761219.html
Copyright © 2020-2023  润新知