随笔 - 218  文章 - 1  评论 - 3819

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的更多相关文章

  1. “全栈2019”Java多线程第一章:认识多线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

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

    http://blog.csdn.net/morewindows/article/details/7392749 系列前言 本系列是本人参加微软亚洲研究院,腾讯研究院,迅雷面试时整理的,另外也加入一些 ...

  3. iOS开发-多线程编程技术(Thread、Cocoa operations、GCD)

    简介 在软件开发中,多线程编程技术被广泛应用,相信多线程任务对我们来说已经不再陌生了.有了多线程技术,我们可以同做多个事情,而不是一个一个任务地进行.比如:前端和后台作交互.大任务(需要耗费一定的时间 ...

  4. C#多线程编程介绍——使用thread、threadpool、timer

    C#多线程编程介绍——使用thread.threadpool.timer 在system.threading 命名空间提供一些使得能进行多线程编程的类和接口,其中线程的创建有以下三种方法:thread ...

  5. .net 多线程的使用(Thread)

    上篇 net 同步异步 中篇 多线程的使用(Thread) 下篇 net 任务工厂实现异步多线程 Thread多线程概述 上一篇我们介绍了net 的同步与异步,我们异步演示的时候使用的是委托多线程来实 ...

  6. 多线程——Java中继承Thread类与实现Runnable接口的区别

    线程我只写过继承Thread类的,后来知道java多线程有三种方式,今天首先比较一下常用的继承Thread类和实现Runnable接口的区别. 按着Ctrl键进入Thread之后,发现Thread类也 ...

  7. C#多线程详解(一) Thread.Join()的详解

    bicabo   C#多线程详解(一) Thread.Join()的详解 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程 ...

  8. “全栈2019”Java多线程第十章:Thread.State线程状态详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. Day24_多线程第一天

    1.线程 1.概述      宏观来讲      进程:就是正在运行的程序      线程:就是进程的执行路径,执行单元 2.创建并启动线程的两种方式(掌握)      1.定义一个类继承Thread ...

随机推荐

  1. CoreThink开发(十一)首页控制器判断移动设备还是PC并做相应处理

    在home模块Index控制器添加判断代码 application\Home\Controller\IndexController.class.php <?php // +----------- ...

  2. Jupyter Notebook修改目标文件

    默认的路径 如果没有修改配置文件,那么一般就在用户目录下面: 下面各处默认起始目标地址,以防有一天想改回来 I:\shujufenxi\python.exe I:\shujufenxi\cwp.py ...

  3. HTML,CSS,font-family:中文字体的英文名称

    宋体 SimSun 黑体 SimHei 微软雅黑 Microsoft YaHei 微软正黑体 Microsoft JhengHei 新宋体 NSimSun 新细明体 PMingLiU 细明体 Ming ...

  4. Linux系统服务管理 服务管理

    Linux独立服务管理 启动服务 systemctl start 服务名称.service 设置开机自启动 systemctl enable 服务名称.service 停止开机自启动 systemct ...

  5. Linux Shell编程 exit、break、continue

    exit语句 在系统中exit 命令用于退出当前用户的登录状态.在 Shell 脚本中exit 语句是用来退出当前脚本. exit 的语法如下: exit [返回值] 如果在 exit 之后定义了返回 ...

  6. 使用GoogleCode作SVN服务器的一些问题及解决办法

    1.首先最主要的一个问题,就是注册GoogleCode和安装SVN工具. 网上教程很多,不一一赘述.http://www.th7.cn/Program/net/201305/136059.shtml ...

  7. 存储库之mongodb,redis,mysql

    一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性 ...

  8. No module named bz2

    yum install bzip* python2.6 import bz2 python2.7 import bz2 error 解决:sudo cp /usr/lib64/python2.6/li ...

  9. kali安装后配置

    0x00.安装Vmware Tools 由于是在VMware Workstation里面安装的,所以需要首先安装VMware tools工具方便我们Ctrl+C和Ctrl+V,步骤如下: 在VMWar ...

  10. 限制goroutine数量写法

    虽然golang的goroutine可以开启无数个goroutine,但是没有限制也是不行的.我就写一下我对goroutine数量限制的写法 1.初始化goroutine协程池.把goroutine数 ...