线程是进程中某个单一顺序的控制流,是程序运行中的调度单位,是程序执行流的最小单位,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。 线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。 线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序进程本身。

CLR中有三种常用创建和管理线程的方式:Thread、ThreadPool、Task,下面用最简单的例子写出自己对这三种方式的理解:

一、Thread

《捕鱼达人》是大家都玩过的游戏,至于游戏怎么设计我也不太清楚,但我想在这里用自己对线程的理解来用线程描述这个游戏。假如屏幕上随机产生两条鱼,并且游来游去,代码如下:
class Fish
{
public string Name { get; set; } public Fish()
{
Name = "小黄鱼" ;
} public void Move()
{
Console.WriteLine(string .Format("{0}在游来游去......", Name));
}
} class Program
{
static void Main(string[] args)
{
Fish fish = new Fish();
Thread t1 = new Thread(() =>
{
fish.Move();
});
t1.IsBackground = true;
t1.Start(); Fish fish2 = new Fish() { Name = "大鲨鱼" };
Thread t2 = new Thread(() =>
{
fish2.Move();
});
t2.IsBackground = true;
t2.Start(); Console.ReadKey();
}
}
运行后屏幕如下:
小黄鱼在游来游去......
大鲨鱼在游来游去...... 
 

二、ThreadPool

如果鱼潮来临,一下子要产生100条鱼,如果按上面Thread的做法就要开启100条线程,这样对系统资源的损耗太大,这时我们可以用ThreadPool线程池来实现,代码如下:
static void Main(string[] args)
{
Fish fish = new Fish();
Fish fish2 = new Fish() { Name = "大鲨鱼" };
Fish fish3 = new Fish() { Name = "灯笼鱼" };
Fish fish4 = new Fish() { Name = "红鲤鱼" };
Fish fish100 = new Fish() { Name = "灯笼鱼" };
ThreadPool.QueueUserWorkItem(f => { fish.Move(); });
ThreadPool.QueueUserWorkItem(f => { fish2.Move(); });
ThreadPool.QueueUserWorkItem(f => { fish3.Move(); });
ThreadPool.QueueUserWorkItem(f => { fish4.Move(); });
ThreadPool.QueueUserWorkItem(f => { fish100.Move(); });
Console.ReadKey();
}

运行后屏幕如下:

灯笼鱼在游来游去......
大鲨鱼在游来游去......
灯笼鱼在游来游去......
小黄鱼在游来游去......
红鲤鱼在游来游去......
由于多线程是并发执行,由系统分配顺序,所以上面的结果是随机的 

三、Task

Task是.Net4.0中新加的功能,由于ThreadPool对池中的线程不好控制,Task用来弥补,比如在鱼在流动的时候,我开了一个枪和炮的线程用来发射子弹捕鱼,鱼中枪后鱼游动的线程就要结束,结束的时候弹出奖励积分,比如小黄鱼弹出1分,大鲨鱼弹出100分,这是就要用到Task对象的ContinueWith方法,该方法可以在线程结束的时候产生一个回调方法,代码如下:
class Program
{
static void Main(string[] args)
{
//用来取消小黄鱼线程
CancellationTokenSource cts = new CancellationTokenSource (); Fish fish = new Fish();
Fish fish2 = new Fish() { Name = "大鲨鱼" , Score = }; Task t1 = new Task(() => fish.Move(cts.Token), cts.Token);
t1.Start();
//小黄鱼被击中后显示积分
t1.ContinueWith(fish.ShowScore); Task t2 = new Task(() =>fish2.Move(cts.Token), cts.Token);
t2.Start();
//大鲨鱼鱼被击中后显示积分
t2.ContinueWith(fish2.ShowScore); //按任意键发射
Console.ReadKey(); //武器工厂线程池,执行一组任务
Gun gun = new Gun();
LaserGun laserGun = new LaserGun();
TaskFactory taskfactory = new TaskFactory();
Task[] tasks = new Task[]
{
taskfactory.StartNew(()=>gun.Fire()),
taskfactory.StartNew(()=>laserGun.Fire())
};
//执行武器们开火
taskfactory.ContinueWhenAll(tasks, (Task) => { }); //鱼儿们被击中了就会去调显示积分的方法
cts.Cancel();
Console.ReadLine();
}
} class Fish
{
public string Name { get; set; }
public int Score { get; set; } public Fish()
{
Name = "小黄鱼" ;
Score = ;
} /// <summary>
/// 游动
/// </summary>
public void Move(CancellationToken ct)
{
//如果没有被击中,就一直游阿游,用IsCancellationRequested判断
while (!ct.IsCancellationRequested)
{
Console.WriteLine(string .Format("{0}在游来游去......", Name));
Thread.Sleep();
}
} //中枪死亡后显示奖励
public void ShowScore(Task task)
{
Console.WriteLine(string .Format("{0}中弹了,您得到{1}分......" , Name, Score));
}
} abstract class Weapon
{
public string Name { get; set; }
public abstract void Fire();
} class Gun : Weapon
{
public Gun()
: base()
{
Name = "双射枪" ;
}
public override void Fire()
{
Console.WriteLine(string .Format("咻咻咻,{0}向鱼儿们发射子弹......" , Name));
}
} class LaserGun : Weapon
{
public LaserGun()
: base()
{
Name = "激光炮" ;
}
public override void Fire()
{
Console.WriteLine(string .Format("嗖嗖嗖,{0}向鱼儿们发射炮弹......" , Name));
}
}
运行后屏幕如下:
大鲨鱼在游来游去......
小黄鱼在游来游去......
大鲨鱼在游来游去......
小黄鱼在游来游去......
大鲨鱼在游来游去......
小黄鱼在游来游去...... 
按任意键开火后屏幕显示:
大鲨鱼在游来游去......
小黄鱼在游来游去......
大鲨鱼在游来游去......
小黄鱼在游来游去......
大鲨鱼在游来游去......
小黄鱼在游来游去......
咻咻咻,双射枪向鱼儿们发射子弹......
嗖嗖嗖,激光炮向鱼儿们发射子弹......
大鲨鱼中弹了,您得到100分......
小黄鱼中弹了,您得到1分...... 
 
 
from:http://www.cnblogs.com/maitian-lf/p/3678128.html#undefined
 

用《捕鱼达人》去理解C#中的多线程的更多相关文章

  1. 以吃货的角度去理解云计算中On-Premise、IaaS、PaaS和SaaS

    了解云计算的一定都听过四个“高大上”的概念:On-Premise(本地部署),IaaS(基础设施及服务).PaaS(平台即服务)和SaaS(软件即服务),这几个术语并不好理解.不过,如果你是个吃货,还 ...

  2. Java的JAVA_HOME、Path、CLASSPATH环境变量小结,可以借助这三个的配置去理解Oracle中的那几个环境变量的配置作用

    问题:在哪里都能执行java命令,是和JAVA_HOME变量有关系呢还是path中指定的那个java路径呢?? 刚学Java的时候,很多jdk配置教程都要求设置JAVA_HOME.Path.CLASS ...

  3. 用《舌尖2》去理解C#中的多态和开闭原则

    昨天晚上看了<舌尖上的中国2>第一集,特别的感人,尤其是看到帮别人割麦子的麦客,一亩地开价200,雇主只肯给100,脸上的那种纠结和无可奈何.还有长着大眼睛的跳跳鱼,很可爱,不过最终还是被 ...

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

    ArcGIS Engine 中的多线程使用 原文链接 http://anshien.blog.163.com/blog/static/169966308201082441114173/   一直都想写 ...

  5. ArcGIS Engine 中的多线程使用

    转自原文ArcGIS Engine 中的多线程使用 一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题! 大家都了解到ArcGIS中处理大数据量时速 ...

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

    一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题!         大家都了解到ArcGIS中处理大数据量时速度是相当的慢,这时如果你的程序是单线 ...

  7. JAVA中的数据结构 - 真正的去理解红黑树

    一, 红黑树所处数据结构的位置: 在JDK源码中, 有treeMap和JDK8的HashMap都用到了红黑树去存储 红黑树可以看成B树的一种: 从二叉树看,红黑树是一颗相对平衡的二叉树 二叉树--&g ...

  8. js原生捕鱼达人(三)--完结

    先给分享下我写完的效果,github有点卡,我没有压缩代码,不过效果可以看到 https://jasonwang911.github.io/ 转载请注明'转载于Jason齐齐的博客http://www ...

  9. TOP30专访:捕鱼达人陈昊芝

    原文:http://www.csdn.net/article/2012-04-04/313919/1 编者按:3月31日,第四届CocoaChina游戏开发者大会暨Cocos2D-X技术研讨会在北京举 ...

随机推荐

  1. 《图解HTTP》读书笔记(七:通信数据转发程序-代理/网关/隧道)

    HTTP通信时,除客户端和服务器以外,还有一些用于通信数据转发的应用程序,例如代理.网关和隧道,它们可以配合服务器工作.这些服务器和应用程序可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服 ...

  2. mysql-8.0.13在windows上的部署

    1 .下载mysql-8.0.13-x64 官方网站:https://dev.mysql.com/downloads/mysql/ 2.解压到G盘 3.准备my.ini文件保存到解压目录 [mysql ...

  3. C# 多线程之Task(任务

      1.简介 为什么MS要推出Task,而不推Thread和ThreadPool,以下是我的见解: (1).Thread的Api并不靠谱,甚至MS自己都不推荐,原因,它将整个Thread类都不开放给W ...

  4. Django---cookie和session

    Django的cookie和session 一.cookie 二.session 回到顶部 一.cookie 1.特点 1. cookie数据保存在客户端,以key-value存储 2. cookie ...

  5. filter与map函数

    ·filter()函数filter()函数包括两个参数,分别是function和list.该函数根据function参数返回的结果是否为真来过滤list参数中的项,最后返回一个新列表,如下例所示:&g ...

  6. python中利用matplotlib绘图可视化知识归纳

    python中利用matplotlib绘图可视化知识归纳: (1)matplotlib图标正常显示中文 import matplotlib.pyplot as plt plt.rcParams['fo ...

  7. web_app框架

    web app 建立在asyncio的基础上,因此用aiohttp写一个基本的app.py import logging; logging.basicConfig(level=logging.INFO ...

  8. vue.js国际化vue-i18n插件的使用问题,在模版文本、组件方法、jsf方法里的使用

    vue.js国际化vue-i18n插件的使用问题,在模版文本.组件方法.jsf方法里的使用 1.在文本里使用{{$t("xxx")}} <span>{{$t(" ...

  9. [最新]ABP ASP.NET Zero v5.5.2 破解

    参考https://www.cnblogs.com/xajh/p/8428818.html后, 搞定了Abp.AspNetZeroCore.dll.Abp.AspNetZeroCore.Web.dll ...

  10. Java基础总结3

    计算只做加法计算 减法也是加法计算出来的: 1,顺序结构: 按照编写代码的顺序从上而下逐行翻译执行: 特点:每行代码都能被执行到且被执行一次: 2,选择结构看条件: 条件为true(成立)执行代码块: ...