【转载】5天不再惧怕多线程——第一天 尝试Thread

原本准备在mongodb之后写一个lucene.net系列,不过这几天用到多线程时才发现自己对多线程的了解少之又少,仅仅停留在lock上面,

故这几天看了下线程参考手册结合自己的心得整理一下放在博客上作为自己的学习笔记。

好了,我们知道“负载”是一个很时尚,很牛X的玩意,往大处说,网站需要负载,数据库需要负载。往小处说,线程也需要负载,面对海量的

用户请求,我们的单线程肯定扛不住,那么怎么办,一定要负载,所以说多线程是我们码农必须要熟练掌握的一门技术。

在framework中给我们提供了一个Threading命名空间,下面是一个msdn上不完整的截图:

在后面的系列中我也是主要整理这几个类的使用方法和应用场景。

一:Thread的使用

我们知道这个类代表处理器线程,在Thread中有几个比较常用和重要的方法。

<1> sleep:  这个算是最简单的了。

<2> join:    这个可以让并发行处理变成串行化,什么意思呢?上代码说话最清楚。

 1 class Test 2 { 3     static void Main() 4     { 5         Thread t = new Thread(Run); 6  7         t.Start(); 8  9         //Join相当于把Run方法内嵌如此10         t.Join();11 12         //该死的t.Join(),害的我主线程必须在你执行完后才能执行。13         Console.WriteLine("我是主线程:" + Thread.CurrentThread.GetHashCode());14     }15 16     static void Run()17     {18         //等待5s19         Thread.Sleep(5000);20 21         Console.WriteLine("我是线程:" + Thread.CurrentThread.GetHashCode());22     }23 }

<3> Interrupt和Abort:这两个关键字都是用来强制终止线程,不过两者还是有区别的。

① Interrupt:  抛出的是 ThreadInterruptedException 异常。

Abort:  抛出的是  ThreadAbortException 异常。

② Interrupt:如果终止工作线程,只能管到一次,工作线程的下一次sleep就管不到了,相当于一个

contine操作。

Abort:这个就是相当于一个break操作,工作线程彻底死掉。

Interrupt:

 1 namespace Test 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             Thread t = new Thread(new ThreadStart(Run)); 8  9             t.Start();10 11             //阻止动作12             t.Interrupt();13 14             Console.Read();15         }16 17         static void Run()18         {19             for (int i = 1; i <= 3; i++)20             {21                 Stopwatch watch = new Stopwatch();22 23                 try24                 {25                     watch.Start();26                     Thread.Sleep(2000);27                     watch.Stop();28 29                     Console.WriteLine("第{0}延迟执行:{1}ms", i, watch.ElapsedMilliseconds);30                 }31                 catch (ThreadInterruptedException e)32                 {33                     Console.WriteLine("第{0}延迟执行:{1}ms,不过抛出异常", i, watch.ElapsedMilliseconds);34                 }35             }36         }37     }38 }

Abort:   工作线程直接退出,不带走一片云彩。

 1 namespace Test 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             Thread t = new Thread(new ThreadStart(Run)); 8  9             t.Start();10 11             Thread.Sleep(100);12 13             //阻止动作14             t.Abort();15 16             Console.Read();17         }18 19         static void Run()20         {21             for (int i = 1; i <= 3; i++)22             {23                 Stopwatch watch = new Stopwatch();24 25                 try26                 {27                     watch.Start();28                     Thread.Sleep(2000);29                     watch.Stop();30 31                     Console.WriteLine("第{0}延迟执行:{1}ms", i, watch.ElapsedMilliseconds);32                 }33                 catch (ThreadAbortException e)34                 {35                     Console.WriteLine("第{0}延迟执行:{1}ms,不过抛出异常", i, watch.ElapsedMilliseconds);36                 }37             }38         }39     }40 }

二:线程使用场景

可能线程的使用有点类似wcf,做一些耗时但不很及时的需求,比如可以开线程下图片,连接数据库等等,当然线程可以用来做负载,这里就做

一个小demo,找一个美女网站,面对如此多的图片,一个线程真的吃不消啊,

看了下网站主体上有4个tab页,那么我们就开4个线程来负载

  1  class Program  2     {  3         static void Main(string[] args)  4         {  5             string[] str = { "model", "sexy", "belle", "stars" };  6   7             for (int url = 0; url < str.Length; url++)  8             {  9                 Thread thread = new Thread(DownLoad); 10  11                 thread.Start(str[url]); 12             } 13             Console.Read(); 14         } 15  16         public static void DownLoad(object category) 17         { 18             string url = string.Empty; 19  20             for (int purl = 9014; purl > 10; purl--) 21             { 22                 for (int pageSize = 0; pageSize < 20; pageSize++) 23                 { 24                     try 25                     { 26                         if (pageSize == 0) 27                             url = "http://www.mm8mm8.com/" + category + "/" + purl + ".html"; 28                         else 29                             url = "http://www.mm8mm8.com/" + category + "/" + purl + "_" + pageSize + ".html"; 30  31                         //创建http链接 32                         var request = (HttpWebRequest)WebRequest.Create(url); 33  34                         request.Timeout = 1000 * 5;    //5s过期 35  36                         var response = (HttpWebResponse)request.GetResponse(); 37  38                         Stream stream = response.GetResponseStream(); 39  40                         StreamReader sr = new StreamReader(stream); 41  42                         string content = sr.ReadToEnd(); 43  44                         var list = GetHtmlImageUrlList(content); 45  46                         WebClient client = new WebClient(); 47  48                         string[] directory = { @"C:\MM\", @"D:\MM\", @"E:\MM\", @"F:\MM\" }; 49  50                         var directoryName = directory[new Random().Next(0, directory.Length)]; 51  52                         if (!Directory.Exists(directoryName)) 53                             Directory.CreateDirectory(directoryName); 54  55                         var fileName = string.Empty; 56  57                         if (list.Count == 0) 58                         { 59                             Console.WriteLine("时间:" + DateTime.Now + " 当前网址:" + url + "  未发现图片"); 60                             break; 61                         } 62  63                         try 64                         { 65  66                             fileName = category + "_" + purl + "_" + (pageSize + 1) + ".jpg"; 67  68                             var localFile = directoryName + fileName; 69  70                             var imageRequest = (HttpWebRequest)WebRequest.Create(list[0]); 71  72                             imageRequest.Timeout = 1000 * 5;  //5s 超时 73  74                             var imageResponse = (HttpWebResponse)imageRequest.GetResponse(); 75  76                             var s = imageResponse.GetResponseStream(); 77  78                             Image image = Image.FromStream(s); 79  80                             image.Save(localFile); 81  82                             image.Dispose(); 83  84                             Console.WriteLine("时间:" + DateTime.Now + "  图片:" + fileName + " 已经下载   存入磁盘位置:" + localFile); 85  86                         } 87                         catch (Exception e) 88                         { 89                             Console.WriteLine("时间:" + DateTime.Now + " 当前图片:" + fileName + " 错误信息:" + e.Message); 90                             continue; 91                         } 92                     } 93                     catch (Exception ex) 94                     { 95                         Console.WriteLine("时间:" + DateTime.Now + " 当前网址:" + url + " 错误信息:" + ex.Message); 96                     } 97                 } 98             } 99         }100 101         /// <summary> 102 /// 取得HTML中所有图片的 URL。 103 /// </summary> 104 /// <param name="sHtmlText">HTML代码</param> 105 /// <returns>图片的URL列表</returns> 106         public static List<string> GetHtmlImageUrlList(string sHtmlText)107         {108             // 定义正则表达式用来匹配 img 标签 109             Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""‘]?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""‘<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);110 111             // 搜索匹配的字符串 112             MatchCollection matches = regImg.Matches(sHtmlText);113 114             List<string> sUrlList = new List<string>();115 116             // 取得匹配项列表 117             foreach (Match match in matches)118                 sUrlList.Add(match.Groups["imgUrl"].Value);119             return sUrlList;120         }121     }

三:对线程的一些思考

我们知道线程的优点还是比较多的,每个线程都需要默认的堆栈空间,所以说线程数受到内存空间大小的限制,如果线程数开的太多

反而适得其反,进程被分配的时间片会被线程分的更细,也就导致了处理器需要更频繁的在线程之间来回切换。

转载地址:http://www.cnblogs.com/huangxincheng/archive/2012/03/14/2395279.html

时间: 2024-11-08 18:49:06

【转载】5天不再惧怕多线程——第一天 尝试Thread的相关文章

【转载】5天不再惧怕多线程——第五天 线程池

说到多线程,不可不说线程池,C#中关于池的概念很多,今天来整理下ThreadPool的使用. 是的,如果你很懒,如果你的执行任务比较短,如果你不想对线程做更精细的控制,那么把这些繁琐的东西丢给线程池吧. 一:ThreadPool 好了,下面看看TheadPool下有哪些常用的方法. 1:GetMaxThreads,GetMinThreads 首先我们肯定好奇线程池到底给我们如何控制线程数,下面就具体的看一看. 1 class Program 2 { 3 static void Main(stri

【转载】5天不再惧怕多线程——第二天 锁机制

当多个线程在并发的时候,难免会碰到相互冲突的事情,比如最经典的ATM机的问题,并发不可怕,可怕的是我们没有能力控制. 线程以我的理解可以分为三种 ① 锁. ② 互斥. ③ 信号. 好,这一篇主要整理"锁",C#提供了2种手工控制的锁 一:  Monitor类 这个算是实现锁机制的纯正类,在锁定的临界区中只允许让一个线程访问,其他线程排队等待.主要整理为2组方法. 1:Monitor.Enter和Monitor.Exit 微软很照护我们,给了我们语法糖Lock,对的,语言糖确实减少了我们

【转载】5天不再惧怕多线程——第四天 信号量

今天整理"信号量"的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在framework里面主要有三种. <1>:ManualResetEvent <2>:AutoResetEvent <3>: Semaphore 好,下面就具体看看这些玩意的使用. 一:ManualResetEvent 该对象有两种信号量状态True和False,好奇的我们肯定想知道True和False有什么区别,稍后的例子见分晓,有三个方法值得学习一下. 1:W

【转载】5天不再惧怕多线程——第三天 互斥体

没想到我的前两篇文章还挺受欢迎的,谢谢大家,今天整理下Mutex的使用. 一:Mutex 首先看下MSDN对它的解释: 不错,出现了一个亮点,可用于"进程间同步",既然进程间都可以同步,那线程同步对它来说不是小菜一碟吗?好的,还是看下Mutex在 线程中发挥的神奇功效. 1: 线程间同步 Metux中提供了WatiOne和ReleaseMutex来确保只有一个线程来访问共享资源,是不是跟Monitor很类似,下面我还是举个简单的例子, 注意我并没有给Metux取名字. 1 class

第一天 尝试Thread

一:Thread的使用 我们知道这个类代表处理器线程,在Thread中有几个比较常用和重要的方法. <1> sleep:  这个算是最简单的了. <2> join:    这个可以让并发行处理变成串行化,什么意思呢?上代码说话最清楚. 1 class Test 2 { 3 static void Main() 4 { 5 Thread t = new Thread(Run); 6 7 t.Start(); 8 9 //Join相当于把Run方法内嵌如此 10 t.Join(); 1

秒杀多线程第一篇 多线程笔试面试题汇总 ZZ 【多线程】

http://blog.csdn.net/morewindows/article/details/7392749 系列前言 本系列是本人参加微软亚洲研究院,腾讯研究院,迅雷面试时整理的,另外也加入一些其它IT公司如百度,阿里巴巴的笔试面试题目,因此具有很强的针对性.系列中不但会详细讲解多线程同步互斥的各种“招式”,而且会进一步的讲解多线程同步互斥的“内功心法”.有了“招式”和“内功心法”,相信你也能对多线程挥洒自如,在笔试面试中顺利的秒杀多线程试题. ----------------------

秒杀多线程第一篇 多线程笔试面试题汇总

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 系列前言 本系列是本人参加微软亚洲研究院,腾讯研究院,迅雷面试时整理的,另外也加入一些其它IT公司如百度,阿里巴巴的笔试面试题目,因此具有很强的针对性.系列中不但会详细讲解多线程同步互斥的各种“招式”,而且会进一步的讲解多线程同步互斥的“内功心法”.有了“招式”和“内功心法”,相信你也能对多线程挥洒自如,在笔试面试中顺利的秒杀多线程试题. -------------------------------------华丽的分割线

[转] 从此不再惧怕URI编码:JavaScript及C# URI编码详解

混乱的URI编码 JavaScript中编码有三种方法:escape.encodeURI.encodeURIComponent C#中编码主要方法:HttpUtility.UrlEncode.Server.UrlEncode.Uri.EscapeUriString.Uri.EscapeDataString JavaScript中的还好,只提供了三个,C#中主要用的就有这么多,还没有列出其他编码(HTML),一多就弄不明白,弄不明白就心生恐惧,心生恐惧就变得苦逼,本文就向大家详细解释在JavaSc

[转载]ArcGIS Engine 中的多线程使用

ArcGIS Engine 中的多线程使用 原文链接 http://anshien.blog.163.com/blog/static/169966308201082441114173/   一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题! 大家都了解到ArcGIS中处理大数据量时速度是相当的慢,这时如果你的程序是单线程的,那可就让人着急坏了,不知道处理到什么地步,不能操作其他的功能,无奈~~如果在这时你能够想到用多线程技术,那就来试试该如何