博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
5天不再惧怕多线程——第一天 尝试Thread
阅读量:4560 次
发布时间:2019-06-08

本文共 8285 字,大约阅读时间需要 27 分钟。

     原本准备在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 //等待5s 19 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 try 24 {
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 try 26 {
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 /// 102 /// 取得HTML中所有图片的 URL。 103 /// 104 /// HTML代码 105 ///
图片的URL列表
106 public static List
GetHtmlImageUrlList(string sHtmlText) 107 {
108 // 定义正则表达式用来匹配 img 标签 109 Regex regImg = new Regex(@"
<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?
[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase); 110 111 // 搜索匹配的字符串 112 MatchCollection matches = regImg.Matches(sHtmlText); 113 114 List
sUrlList = new List
(); 115 116 // 取得匹配项列表 117 foreach (Match match in matches) 118 sUrlList.Add(match.Groups["imgUrl"].Value); 119 return sUrlList; 120 } 121 }

三:对线程的一些思考

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

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

 

转载于:https://www.cnblogs.com/huangxincheng/archive/2012/03/14/2395279.html

你可能感兴趣的文章
工作笔记——禁用浏览器的返回按钮
查看>>
免费获得盛大网盘EverBox125G容量方法
查看>>
如何用spidermonkey在python里调用javascript代码
查看>>
2016级算法第一次练习赛-A.群鸦的盛宴
查看>>
浅谈深度学习和本体间的关系
查看>>
js下载文件
查看>>
python 中的高级函数filter()
查看>>
vim配置
查看>>
python创建系统时间字符串
查看>>
服务器上产看报错的日志的方法
查看>>
软件安装
查看>>
黑盒测试实践—第四天
查看>>
luogu P4448 [AHOI2018初中组]球球的排列
查看>>
[No000016C]做企业分析的三个重要工具
查看>>
win7每天出现taskeng.exe进程的解决方案
查看>>
c++:资源管理(RAII)、new/delete的使用、接口设计与声明、swap函数
查看>>
React Children
查看>>
大数据等最核心的关键技术:32个算法
查看>>
Maven多模块项目搭建
查看>>
redis列表list
查看>>