概念引用:http://blog.csdn.net/yujie_yang/article/details/53173752
多线程和多进程的区别:任务管理器里各种不同的进程就是多进程,或者是你同时运行多个”.exe’程序就可以理解为多进程,多进程是要更多消耗CPU资源的。
多线程是相对于进程里更小的单位,比如3个线程在1个进程里进行不同的操作,他们所拥有的资源就是那个进程里的资源,不会占用更多资源,只是通过线程更合理的分配资源。
一.单线程
在很久以前的MS-DOS时代时代,都是单任务的,比如说我想玩潜艇大战和听歌,很抱歉,只能选择玩潜艇大战或者听歌,不能同时进行。
所以我只能先玩潜艇大战,玩腻了就关掉游戏打开音乐播放器听一首《七里香》来舒缓心绪,模拟的程序如下:
public static void game()
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " 玩潜艇大战");
}
public static void music()
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " 听七里香");
}
static void Main(string[] args)
{
game();
music();
Console.ReadKey();
}
我们控制台输出的结果为:
2016-11-15 04:30:56.724 玩潜艇大战
2016-11-15 04:30:56.755 听七里香
二.双线程
当然,我们现在的时代大可不必那么老实的先干什么再干什么,我们可以选择边玩游戏,边听歌。模拟代码如下:
public static void game()
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " 玩潜艇大战");
}
public static void music()
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") + " 听七里香");
}
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(game));//开始一个玩游戏的线程
Thread t2 = new Thread(new ThreadStart(music));//开始一个听音乐的线程
t1.Start();
t2.Start();
Console.ReadKey();
}
控制台输出结果为:
2016-11-15 04:43:48.987 玩潜艇大战
2016-11-15 04:43:48.988 听七里香
2016-11-15 04:45:19.315 听七里香
2016-11-15 04:45:19.315 玩潜艇大战
2016-11-15 04:46:38.513 听七里香
2016-11-15 04:46:38.512 玩潜艇大战
这三组结果可以看出,运用线程后玩游戏和听音乐可以同时展开,两个任务不分先后时间差明显比单线程模式要少,更合理的利用了资源。
三.三线程
其实以上的代码中还隐藏了一个线程,就是主线程Main(string[] args),我们下面再改进一下代码看看三个线程运行时的情况。
核心代码更改如下:
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(game));//开始一个玩游戏的线程
Thread t2 = new Thread(new ThreadStart(music));//开始一个听音乐的线程
t1.Priority = ThreadPriority.BelowNormal;
t2.Priority = ThreadPriority.Lowest;
t1.Start();
t2.Start();
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff") +" 边玩游戏边听音乐");
Console.ReadKey();
}
控制台输出结果:
2016-11-15 05:01:15.598 听七里香
2016-11-15 05:01:15.575 边玩游戏边听音乐
2016-11-15 05:01:15.598 玩潜艇大战
2016-11-15 05:03:25.966 听七里香
2016-11-15 05:03:25.964 边玩游戏边听音乐
2016-11-15 05:03:25.965 玩潜艇大战
2016-11-15 05:03:50.022 听七里香
2016-11-15 05:03:50.001 边玩游戏边听音乐
2016-11-15 05:03:50.001 玩潜艇大战
不知道大家注意到没有,主线程每次都是先执行的,并且听音乐好像也总是比玩游戏要晚执行,因为代码里我有一个改动:
t1.Priority = ThreadPriority.BelowNormal;
t2.Priority = ThreadPriority.Lowest;
没错,我设置了线程的优先级,t2代表听音乐的线程优先级比t1玩游戏的优先级要低。对应现实来说就好像我要先打开游戏玩着玩着觉得配乐不好听,所以我选择静音再点开我最爱的《七里香》,这样玩游戏就更加带劲了!
四.线程的优先级
线程的优先级可以通过Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5个优先等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。普通线程的优先级默认为Normal;如果想有更高的优先级,可设置为AboveNormal或Highest;如果想有较低的优先级,可设置为BelowNormal或Lowest。
也许有人会问那之前的例子主线程总是先完成是不是优先级默认要高呢?其实不是的,主线程和工作线程的优先级相同,也是交替进行,被执行的概率大体相同,至于每次先完成是因为主线程会先启动,只有启动了主线程才能开启其他工作线程。
要注意的是:系统优先执行优先级较高的线程,但这只意味着优先级较高的线程占有更多的CPU时间,并不意味着一定要先执行完优先级较高的线程,才会执行优先级较低的线程。
五.多线程同步
对多线程进行同步,主要用到的是MethodImplAttribute 类 和 SynchronizationAttribute 类,本质上还是基于Lock的实现的。
一个简单如小明和小红两个人用都是主附银行卡,两个人都可以对帐户进行操作,比如帐户余额1000元,比如两个人几乎同时进行取钱600元的操作。
引入MethodImplAttribute 类:
在使用 MethodImplAttribute 类之前需要引用 System.Runtime.Remoting.Contexts 命名空间,System.Runtime.Remoting.Contexts 命名空间包含的一些属性将影响CLR 在运行期间的行为,MethodImplAttribute 就是这样一个属性,MethodImplAttribute类的一个构造函数把MethodImplOptions枚举作为其参数,MethodImplOptions 枚举有一个字段Synchronized,,它指定在任一时刻只允许一个线程访问这个方法。
具体参考详解连接 http://www.cnblogs.com/miniwiki/archive/2010/06/18/1760540.html