多线程

因为web application做的比较多,所以多线程方面的知识很欠缺。最近被打击了,狠下心来恶补一下。一步一步来,在这里记个脚印吧,自己以后也可以看看。主要写给自己以后看的,就不装大师了,很多概念就不详细解释了。

 

1.线程和进程

怎么说呢,我自己的理解是线程是指对cpu说的,进程是跟内存有关的。一个进程里面可能有多个线程。比如一个ie8(及以前版本)浏览器,打开很多个tab,任务管理器里面只显示进程,但是至少一个tab是由一个线程管理的。

所以这就引出了多线程。 

2.多线程

顾名思义,就是多个线程同时工作。现在的cpu都双核甚至多核的,所以多线程程序更能体现出多核的优势。

2.1 传统方式

以前,线程是通过Thread类来操作的,namespace System.Threading中 .先写个例子,直观的感觉下。

 basic

 

2.2  较新方式

随着.net framework的升级,多线程变得越来越简单,好用。在.net4.0中,多了很多新的使用多线程的方式。通过 System.Threading.Tasks.Parallel and System.Threading.Tasks.Task classes, Parallel LINQ (PLINQ) 我们使用多线程的难度简化了。也举个TPL(task paralell library)并行例子吧。

以前,我们循环一个list中数据项时候

 

foreach (var item in Lst)
{
     process(ExpensiveFunction)//注意,ExpensiveFunction指一个很花时间的方法,比如画图。。。
}

这样就 很花时间,因为是一个一个执行的。 

如果使用并行的方式 

Lst.AsParallel().ForAll(x => (x.Start(ExpensiveFunction)); 

这样一句就可以了,如果是多核的计算机,并行的方式极有可能提高效率的。但是如果我们只是一个非常简单的计算,就不必了

比如 ,num % 2实在是非常快速的操作,似乎就没有那么必要的去并行了

// Parallel equivalent 
Parallel.ForEach(sourceCollection, item => yeild return item % 2));

再举个PLINQ的例子。(PLINQ就是LINQ的并行方式)
var result = list.where(item=>item<100).select(n=>Fabtorial(n))//Fabtorial(N)求N阶层
//顺序的方式运行
改成并行的方式,我们只需要简单的加上AsParalell()
var result=list.AsParalell().where(x=>x<100).select(n=>Fabtorial(n))
这里和TPL一样,只有当每个select条件都是比较花费时间的时候才时候用PLINQ,否则你就是会欲速则不达了。

3.TreadPool
用Tread类操作线程,还是比较麻烦的事情,TheradPool则省心些,ThreadPool会自己对线程进行管理,比如你不需要自己去process.Start(),他们自己会启动,并且据说,效率较高。
例子:
//ThreadPool demo public class ThreadPoolDemo {

// Wrapper method for use with thread pool. public void ThreadPoolCallback(object threadContext) { int threadIndex = (int)threadContext; Console.WriteLine("thread {0} started...", threadIndex); Thread.Sleep(100); Console.WriteLine("thread {0} finished...", threadIndex); } }

 

在main中

static void Main(string[] args)  

{

 

const int FibonacciCalculations = 10; Console.WriteLine("launching {0} tasks...", FibonacciCalculations); for (int i = 0; i < FibonacciCalculations; i++) { ThreadPool.QueueUserWorkItem(new ThreadPoolDemo().ThreadPoolCallback,i); }
 

 

ThreadPool使用很简单,主要的方法是QueueUserWorkItem,它的缺点同样明显,因为是统一管理,你自己就没有办法去管理某一个Thread的运行、优先级等等,而Thread是可以做到的。

 4.Thread的优先级

Thread优先级是个枚举变量,共五个,ThreadPriority.Highest,ThreadPriority.AboveNomal, ThreadPriority.Nomal, ThreadPriority.belowNamal,ThreadPriority.Lowest。默认是Nomal

当有多个线程时候,级别高的先占据cpu资源,优先执行。

当一个低级别的线程正在执行时候,很可能被高级别的线程抢占,等高级别执行完后才接着执行

 注意一点的是,系统给线程分配执行的最小时间片内,一个低级的线程必须执行完后才会被抢占,所以说也不是低级的线程立刻被抢占,必须是它当前最小时间片内完成后才会被抢占。例子:

 static void PriorityTest()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("  {0} worker thread reach {1} ...", Thread.CurrentThread.Name, i));
            }

        } 

 

main()

  Thread t1 = new Thread(PriorityTest);

            t1.Name = "t1";
            t1.Priority = ThreadPriority.Lowest;
            Thread t2 = new Thread(PriorityTest);
            t2.Name = "t2";
            t2.Priority = ThreadPriority.AboveNormal;
    t1.Start();

            t2.Start();  

} 

 

 如果是单核的计算机,执行的结果应该类似于

t1  worker thread reach 0

t2 worker thread reach 0

t2 worker thread reach 1

....

t2 worker thread reach 9 

t1 worker thread reach 1...

但是当前的计算机基本都是多核的,所以可能会不是完全这样的顺序,但应该是t2先执行完,t1后 

 

posted on 2011-12-28 15:27  鹤翔九天  阅读(202)  评论(0)    收藏  举报

导航