class Program { static void Main(string[] args) { /** //前台线程和后台线程组成线程 所以每一个线程都有一个IsBackground //前台线程必须执行完程序才会退出 //后台程序在程序退出时一并退出 //当创建一个线程时默认是后台线程 Console.WriteLine(Thread.CurrentThread.IsBackground); Console.WriteLine(Thread.GetCurrentProcessorId().ToString()); Thread th = new Thread(_=>{ Thread t = _ as Thread; //注释以后前台线程变后台线程 那么现在你在console.read之后程序直接执行完毕 不会再执行 "子线程结束" //t.IsBackground = true; Console.WriteLine("子线程开始工作"); Console.WriteLine(t?.IsBackground); Console.WriteLine(Thread.GetCurrentProcessorId().ToString()); //挂起线程取决于此条命令在哪个线程执行 Thread.Sleep(2000); Console.WriteLine("子线程结束!"); }); th.Start(th); Thread.Sleep(1000); Console.WriteLine("主进程完毕"); Console.Read(); */ //设置优先级(提供线程被调用的概率) // ThreadPriority(); //Abort的使用 //ThreadAbort(); //ThreadJion(); ThreadLock(); Console.Read(); } /// <summary> /// 线程优先级依赖于windows内部的线程调度 /// 线程如果处于等待状态会释放掉他所持有的cpu 即使没有手动释放CPU也会被线程调度器抢占CPU /// 如果多个线程有相同的优先级 那么windows会为我们创建一个同优先级的队列然后循环执行 /// 线程的优先级是动态调整的 所以低优先级的也会随着时间提升 /// 也就是说 手动提升线程的优先级 对系统而言只是提高了被调用的概率 /// </summary> static void ThreadPriority() { Thread thread = new Thread(()=> { Console.WriteLine("test thread"); }); Console.WriteLine(thread.Priority); thread.Start(); thread.Priority = System.Threading.ThreadPriority.Highest; Console.WriteLine(thread.Priority); Console.Read(); } static void ThreadAbort() { Thread t = new Thread(_=> { Console.WriteLine("线程:"+Thread.CurrentThread.Name+" 终止"); try { //使用Abort的方式停止线程会抛出异常 Thread.CurrentThread.Abort(); } catch (Exception ex) { //当Abort抛出异常时可以用ResetAbort取消停止 //可以尝试注释词条查看效果 Thread.ResetAbort(); } Console.WriteLine("你看我打印不"); }); t.Name = "testThread"; t.Start(); } /// <summary> /// 阻塞其他线程(包括主线程) 直到找个线程执行完才会执行其他线程 /// 通俗的说 就是这个join你放到哪个线程阻塞哪个线程 /// </summary> static void ThreadJion() { Thread minThree = new Thread(() => print(3000, "线程minThread")); //挂2000 Thread th = new Thread(()=>print(2000,"线程th")); //挂1000 Thread th1 = new Thread(() => { minThree.Start(); //让线程 minthree阻塞本线程 minThree.Join(); print(1000, "线程th1"); }); th.Start(); th1.Start(); //让th1阻塞主线程 th1.Join(); //此时minthree阻塞了th1 th先被打印了 而后打印了minthree 和 th1 再然后打印汉字 Console.WriteLine("我是主线程我想看看谁先执行完毕"); } public static void print(int time,string str) { Thread.Sleep(time); Console.WriteLine(str); } /// <summary> /// lock关键字锁住某个资源让让线程有序使用 /// </summary> public string name = ""; public static void ThreadLock() { Program pg = new Program(); pg.name = "尹程"; //开两个线程抢下资源 Thread t1 = new Thread(()=>printName(pg,"1")); Thread t2 = new Thread(() => printName(pg,"2")); t1.Start(); //提升一下被调用的概率 t1.Priority = System.Threading.ThreadPriority.AboveNormal; t2.Start(); } private static object obj; public static void printName(object pg,string mark) { //锁住资源 注释掉lock多执行几次看看效果就明白了 //锁住了所有program类的实例 lock (typeof(Program)) { for (int i = 0; i < 3; i++) { Console.WriteLine((pg as Program).name + " " + mark); } } //我这里所著的是一个类的实例对象 //不要锁字符串 字符串被C#特殊处理了 lock("某个字符串变量")与lock(typeof(string))是一样的效果 lock (pg) { } //锁住一个私有静态的全局变量 //这样搞主要是为了静态的单例使用 //比如pureMVC把几个层的单例全部放在寄存器里读取 特意锁了个私有的静态变量 保证单例实例化的时候不会被其他线程同时执行 lock (obj) { } } public static void AboutMonitor() { //lock在使用时会被CLR(C#的运行环境)解释为Monitor静态类 //lock(obj){(这个括号相当于) Monitor.Enter(obj); //释放掉obj身上的锁 注意 解锁时 一定要在 Enter和Exit之间 Monitor.Wait(obj); //只能锁Enter中锁住的资源 Monitor.Pulse(obj); //} (这个括号相当于) Monitor.Exit(obj); } }