扎实基础_多线程
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("没有了"); } } } } }
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/12761219.html