5天不再惧怕多线程——第一天 尝试Thread
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 //等待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 /// <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 }

三:对线程的一些思考
我们知道线程的优点还是比较多的,每个线程都需要默认的堆栈空间,所以说线程数受到内存空间大小的限制,如果线程数开的太多
反而适得其反,进程被分配的时间片会被线程分的更细,也就导致了处理器需要更频繁的在线程之间来回切换。
————————————————————————————————————————————————————————————
————————————————————————————————————————————————————————————
友情提示:如果不喜欢看文章,可以移步本系列的 C#IL解读完整视频 【一把伞的钱哦】
5天不再惧怕多线程——第一天 尝试Thread的更多相关文章
- “全栈2019”Java多线程第一章:认识多线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 秒杀多线程第一篇 多线程笔试面试题汇总 ZZ 【多线程】
http://blog.csdn.net/morewindows/article/details/7392749 系列前言 本系列是本人参加微软亚洲研究院,腾讯研究院,迅雷面试时整理的,另外也加入一些 ...
- iOS开发-多线程编程技术(Thread、Cocoa operations、GCD)
简介 在软件开发中,多线程编程技术被广泛应用,相信多线程任务对我们来说已经不再陌生了.有了多线程技术,我们可以同做多个事情,而不是一个一个任务地进行.比如:前端和后台作交互.大任务(需要耗费一定的时间 ...
- C#多线程编程介绍——使用thread、threadpool、timer
C#多线程编程介绍——使用thread.threadpool.timer 在system.threading 命名空间提供一些使得能进行多线程编程的类和接口,其中线程的创建有以下三种方法:thread ...
- .net 多线程的使用(Thread)
上篇 net 同步异步 中篇 多线程的使用(Thread) 下篇 net 任务工厂实现异步多线程 Thread多线程概述 上一篇我们介绍了net 的同步与异步,我们异步演示的时候使用的是委托多线程来实 ...
- 多线程——Java中继承Thread类与实现Runnable接口的区别
线程我只写过继承Thread类的,后来知道java多线程有三种方式,今天首先比较一下常用的继承Thread类和实现Runnable接口的区别. 按着Ctrl键进入Thread之后,发现Thread类也 ...
- C#多线程详解(一) Thread.Join()的详解
bicabo C#多线程详解(一) Thread.Join()的详解 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程 ...
- “全栈2019”Java多线程第十章:Thread.State线程状态详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Day24_多线程第一天
1.线程 1.概述 宏观来讲 进程:就是正在运行的程序 线程:就是进程的执行路径,执行单元 2.创建并启动线程的两种方式(掌握) 1.定义一个类继承Thread ...
随机推荐
- filebeat 简介安装
Filebeat is a lightweight shipper for forwarding and centralizing log data. Installed as an agent on ...
- static关键字注意事项
/* static关键字注意事项 A:在静态方法中是没有this关键字的 如何理解呢? 静态是随着类的加载而加载,this是随着对象的创建而存在. 静态比对象先存在. B:静态方法只能访问静态的成员变 ...
- 0505-Hystrix保护应用-Turbine集群状态监控
https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_turbine
- blogCMS中出现的错误整理
1.在写日期归档的时候,出现如下错误: not enough values to unpack (expected 2, got 1) 出现这个错误是因为:字符串需要能够split成2份才能赋值给2个 ...
- DP专题·四(树形dp)
1.poj 115 TELE 题意:一个树型网络上有n个结点,1~n-m为信号传送器,n-m+1~n为观众,当信号传送给观众后,观众会付费观看,每铺设一条道路需要一定费用.现在求以1为根,使得收到观众 ...
- s5_day13作业
#对之前文件进行的增删改查操作实现日志操作,日志输出用户进行过的操作. def log(): import logging logger_obj=logging.getLogger() logger_ ...
- 查询前几条记录 top limit
SQL Server 数据库中的Top关键字可实现查询数据库表中的前几条数据,但是需要注意的是,Top关键字只能在SQL Server数据库中可以使用,而在MySQL数据库中就要使用具有同样功能的LI ...
- 常用restful路由
tax_categories GET /tax_categories(.:format) tax_categories#index POST /tax_categories(.:format) tax ...
- Eclipse 中安装Browse Deployment Location插件
Browse Deployment Location 功能的插件名称为: Pivotal tc Server Integration for Eclipse 可在Eclippse的Eclipse M ...
- 8月白盒测试课程 - C C++ 白盒测试实践
8月白盒测试课程 - C C++ 白盒测试实践http://gdtesting.cn/news.php?id=36