Threads concepts

(一)线程--简述线程概述及原理 
线程是程序执行的基本原子单位. 一个进程可以由多个线程组成.
在分布式编程中,正确使用线程能够很好的提高应用程序的性能及运行效率. 

实现原理是将一个进程分成多个线程,然后让它们并发异步执行,来提高运行效率.

并发执行并不是同时执行(占有CPU),任意时刻还是只能有一个线程占用CPU,
只不过是它们争夺CPU频繁一些,感觉到他们似乎都在运行.

下面通过一个简单的例子来说明一下它的工作原理

设一个进程要完成两个任务:任务1和任务2
 并且任务1要经历: A1
->B1->C1三个步骤才能完成
     任务2要经历: A2
->B2->C2三个步骤才能完成
  I.如果两个任务同步执行的话完成两个任务是这样执行的:
    
    花费时间段:   
1   2   3   4   5  6
                 A1
->B1->C1->A2->B2-C2
    
     这样从A1一直到c2只能一个一个地执行. 当A1占用CPU执行时,从B1到C2线程只能在等待.  
     甚至它们不相互竞争同一个资源时,也要等待前面的执行完成,自己才能执行


  II.如果两个任务异步执行的话完成两个任务是这样执行的:
   
    花费时间段:   
1   2   3   4   5  6    
                  A1
->B1->C1
                  A2
->B2->C2 
    
     这样,任务1和任务2就分成两个独立的执行对象.  也就是说: 
     A1
->B1->C1 和 A2->B2->C2 是并发执行的. 当A1在执行某个运算时,A2线程可以去做其它
     的一些事情,比如访问磁盘等外部设备等

      对比一下I和II两种执行方式,完成所有任务I需要6个时间段,
  而II只需要3个时间段就完成了(事实上会多一点,因为方式II中的线程轮询CPU比较频繁,在轮询CPU时会花费一些时间);方式II所需时间是I的一半. 所以II完成整个任务要快.
      另一方面,II执行方式,完成每个任务所需的时间可能会花费时间长些,因为I方式是各个线程依次占用CPU执行,当A1占用CPU时,CPU就只为A1服务,当A1执行完后,才让出CPU。II情况就不一样了,它们是异步执行的,轮流使用CPU频繁,经常让出或占有CPU,执行每个线程完成的时间也就会相对长些.

    一般情况下,如果多个线程在执行时都要抢占某一个资源或某几个资源,则最好不用异步线程执行.因为它们是并发执行,很可能同时争夺某个资源有CPU,这时要么执行资源分配算法(比如要判断哪个线程优先级高,这要花费时间),或者是按时间片算法(这样要付出 轮询CUP
/交接/让出CPU 所需的时间).  如果多个线程所需要的系统资源是比较均匀的,这时完全可以让它们异步并发执行,比如: 当一个线程在给客户端
发出消息后,并不是一直在等待此客户端回应,它可以继续处理下一个客户端请求.  

(二)线程
--通过委托异步调用方法 
(一).描述
  先运行个简单的线程示例,认识一下线程
  通过委托调用方法,以及使用AsyncResult判断线程的状态

(二).代码
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace 通过委托异步调用方法

 
//委托声明(函数签名)
 delegate string MyMethodDelegate();

 
class MyClass
 {
  
//要调用的动态方法
  public string MyMethod1()
  {
   
return "Hello Word1";
  }

  
//要调用的静态方法
  public static string MyMethod2()
  {
   
return "Hello Word2";
  }
 }
 
class Class1
 {
  
/// 
  
/// 应用程序的主入口点。
  
/// 

  [STAThread]
  
static void Main(string[] args)
  {
            MyClass myClass 
= new MyClass();
   
   
//方式1:  声明委托,调用MyMethod1
   MyMethodDelegate d = new MyMethodDelegate(myClass.MyMethod1);
   
string strEnd = d();   
   Console.WriteLine(strEnd);

   
//方式2:  声明委托,调用MyMethod2 (使用AsyncResult对象调用)
   d = new MyMethodDelegate(MyClass.MyMethod2); //定义一个委托可以供多个方法使用      
   AsyncResult myResult;   //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
   myResult = (AsyncResult)d.BeginInvoke(null,null);        //开始调用
   while(!myResult.IsCompleted)  //判断线程是否执行完成
   {
    Console.WriteLine(
"正在异步执行MyMethod2 ..");
   }
   Console.WriteLine(
"方法MyMethod2执行完成!");
   strEnd 
= d.EndInvoke(myResult);      //等待委托调用的方法完成,并返回结果  
   Console.WriteLine(strEnd);
   Console.Read();
  }
 }
}


(三)线程
--等待句柄
(一).描述
    本示例代码实现线程等待等待执行,比如一个线程在执行之前要等待所有其它线程或某个线程
先执行完成,或者等待其它线程至少一个执行完成.
(二).代码
    
using System;
    
using System.Runtime.Remoting.Messaging;
    
using System.Threading;

namespace 等待句柄

 
//委托声明(函数签名)
 delegate string MyMethodDelegate();
 
class MyClass
 { 
  
//要调用方法1
  public string Write1()
  {
   
for(double i = 0; i < 100000000000;i++)  //此数值大小可以根据自己的环境修改,
                                                                 
//目的是让此方法延长时间而已
   {
    
//延长时间(模拟实际任务)
   }
   Console.WriteLine(
"执行方法1");
   
return "";
  }

  
//要调用方法2
  public string Write2()
  {
   Console.WriteLine(
"执行方法2");
   
return "22222222222222";
  }

  
//要调用方法3
  public string Write3()
  {
   Console.WriteLine(
"执行方法3");
   
return "33333333333333";
  }

  [STAThread]
  
static void Main(string[] args)
  {
   MyClass myClass 
= new MyClass();
   MyMethodDelegate d1 
= new MyMethodDelegate(myClass.Write1);
   MyMethodDelegate d2 
= new MyMethodDelegate(myClass.Write2);
   MyMethodDelegate d3 
= new MyMethodDelegate(myClass.Write3);

   AsyncResult myResult1,myResult2,myResult3;     
//此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
   myResult1 = (AsyncResult)d1.BeginInvoke(null,null);        //调用   
   
   myResult2 
= (AsyncResult)d2.BeginInvoke(null,null);        
   
   myResult3 
= (AsyncResult)d3.BeginInvoke(null,null); 

   
//建立WaitHandle数组对象
   WaitHandle[] waitHandle = new WaitHandle[3]{myResult1.AsyncWaitHandle,myResult2.AsyncWaitHandle,myResult3.AsyncWaitHandle};

/* 
      try
   {
    //等待三个异步方法中的至少一个执行完成,才继续执行下面的语句
    WaitHandle.WaitAny(waitHandle);
   }
   catch(Exception ex)
   {
    throw new Exception(ex.Message);
   }
*/

   myResult1.AsyncWaitHandle.WaitOne();  
//如果当前异步方法还没有完成,此异步方法执行完毕才往下执行
   myResult2.AsyncWaitHandle.WaitOne();  
   myResult3.AsyncWaitHandle.WaitOne();

/*
   myResult1.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1),false); //如果当前异步方法还没有完成,则等待一秒的时间执行此方法; 如果一秒后此方法还未完成的话,则不再等待,继续往下执行
   myResult2.AsyncWaitHandle.WaitOne();  
   myResult3.AsyncWaitHandle.WaitOne();
*/  
   
   Console.WriteLine(
"测试等待句柄");   //标记语句用.
   Console.Read();
  }
 }
}

(四)线程
--使用线程回调方法 
(一).描述
   此示例演示使用线程回调方法
(二).代码
   
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace 回调

 
//委托声明(函数签名)
 delegate string MyMethodDelegate();

 
class MyClass
 {
  
//调用的方法
  public static string MyMethod()
  {   
   
//Console.WriteLine(System.Threading.Thread.CurrentThread.IsBackground);
   for(int i = 0;i < 3; i++)  //延长时间(模拟实际任务)
   {
    Thread.Sleep(
1000);
   }
   
return "Hello Word";
  }
  
  
//声明委托,调用MyMethod
  private static MyMethodDelegate d = new MyMethodDelegate(MyClass.MyMethod);
  
  
//声明委托,调用AsyncCallbackMethod
  private static System.AsyncCallback a = new System.AsyncCallback(MyClass.AsyncCallbackMethod);  
  
  [STAThread]
  
static void Main(string[] args)
  {
   d.BeginInvoke(a,
null); 
   Console.ReadLine();   
//这句不能去掉,否则主线程执行完成后,子线会会强迫调用Abort()方法销毁掉,也就执行不到回调方法了
  }  
  
  
public static void AsyncCallbackMethod(System.IAsyncResult myIAsyncResult)
  {
   
string strEnd = d.EndInvoke(myIAsyncResult);      //委托调用的方法已经完成,输出其值  
   Console.WriteLine(strEnd);
   Console.Read();
  }
 }
}

(五)线程
--定制线程及设置和获取线程的优先级别 
(一).描述
   此示例演示怎样定制一个线程,并且设置线程的主要属性和获取线程运行时的状态
(二).代码

   
using System;
using System.Threading;
namespace 定制线程
{
 
//委托声明(函数签名)
 
//delegate string MyMethodDelegate();
 class MyClass
 {  
  
public static void Method1()
  {
   
int i;
   
for(i=0;i<10;i++)
   {
    Console.WriteLine(
"Method1 at :" + i.ToString());
    
    
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
    Console.WriteLine("    IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");    
                
    
//是否是后台进程
    Console.WriteLine("    IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");    
    
    
//线程名称
    Console.WriteLine("    Name is " + Thread.CurrentThread.Name.ToString()+" ");    
    
    
//优先级
    Console.WriteLine("    Priority is " + Thread.CurrentThread.Priority.ToString()+" ");    
    
    
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
    Console.WriteLine("    ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");    

    DelayTime(
1);  //延长时间,模拟执行任务
   }
  }
  
public static void Method2()
  {
   
int i;
   
for(i=0;i<10;i++)
   {
    Console.Write(
"Method2 at :" + i.ToString());

    
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
    Console.WriteLine("    IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");    
                
    
//是否是后台进程
    Console.WriteLine("    IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");    
    
    
//线程名称
    Console.WriteLine("    Name is " + Thread.CurrentThread.Name.ToString()+" ");    
    
    
//优先级
    Console.WriteLine("    Priority is " + Thread.CurrentThread.Priority.ToString()+" ");    
    
    
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
    Console.WriteLine("    ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");           

    DelayTime(
1);  //延长时间,模拟执行任务
   }
  }
  
private static void DelayTime(int n)
  {
   DateTime startTime 
= DateTime.Now;
   
while(startTime.AddSeconds(n) > DateTime.Now)
   {
    
//延长时间,模拟实际中的进程
   }
  }

  [STAThread]
  
static void Main(string[] args)
  {           
//   MyMethodDelegate d1 = new MyMethodDelegate(MyClass.Method1);
//   MyMethodDelegate d2 = new MyMethodDelegate(MyClass.Method2);
   
   Thread thread1 
= new Thread(new ThreadStart(Method1));
   thread1.Name 
= "A";   //给线程定义名称
   
//ThreadPriority枚举共五种优先级,由高->低依次为: Highest->AboveNormal->Normal->BelowNormal->Lowest
   
//优先级高的先优先执行,相同优先级的线程具有相同对CPU争夺权力
   thread1.Priority = ThreadPriority.Highest; 

            Thread thread2 
= new Thread(new ThreadStart(Method2));   
   thread2.Name 
= "B";
   thread2.Priority 
= ThreadPriority.Normal;

            thread1.Start();
   thread2.Start();
   Console.Read();
  }
 }
}

(六)线程
--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥) 
(一).描述
   此示例演示分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)
(二).代码
   
using System;
using System.Threading;
using System.Collections;

namespace 加锁_实现临界区互斥操作_

 
//委托声明(函数签名)
 delegate string MyMethodDelegate();

 
class MyClass
 {  
  
private static ArrayList arrList = new ArrayList(); 
  
private static int i = 0;
  
  
public static void Add()
     {
   
//方法一:用 lock 实现
//   lock(arrList)
//   {
//    arrList.Add(i.ToString());
//    i++;
//   }
   
   
//方法二: 用Interlicked类实现
//   System.Threading.Interlocked.Increment(ref i);
//   arrList.Add(i.ToString());

   
//方法三: 用Monitor类实现
   try
   {
    
//I.不限时间
    
//stem.Threading.Monitor.Enter(arrList);  
    
    
//II.在指定时间获得排他锁
    if(System.Threading.Monitor.TryEnter(arrList,TimeSpan.FromSeconds(30))) //在30秒内获取对象排他锁. 灵活运用可以实现防止死锁功能
    {                                                                       //避免互相等待情况。 在一定时间内得不到排他锁,可能是自己
                                                                         
//占用其它排它锁造成的(别的正在等自己正占用的排它锁,而处于等待状态),
                                                                         
//这时可以释放掉自己正占用的排他锁后,再试图去得到想要的对象的排他锁
     arrList.Add(i.ToString());                                        
     i
++;
    }
   }
   
catch
   {
    
//发生异常后自定义错误处理代码
   }
   
finally
   {
    Monitor.Exit(arrList);  
//不管是正常还是发生错误,都得释放对象
   }
  } 
  
  [STAThread]
  
static void Main(string[] args)
  {
   Thread thread1 
= new Thread(new ThreadStart(Add));
   Thread thread2 
= new Thread(new ThreadStart(Add));  
   Thread thread3 
= new Thread(new ThreadStart(Add)); 
   thread1.Start();
   thread2.Start();
   thread3.Start();

   Console.Read();

   
for(int i=0;i<arrList.Count;i++)
   {
    Console.WriteLine(arrList[i].ToString());
   }

   Console.Read();

  }
 }
}

(七)线程
--管理线程(使线程中止,暂停,挂起等) 
(一).描述
   此示例演示怎样设置线程的状态(中止,暂停,挂起等)
(二).代码
   
using System;
using System.Threading;

namespace 管理线程_使线程中止_暂停_挂起等_

 
//委托声明(函数签名)
 delegate string MyMethodDelegate();
 
class MyClass
 {  
  
public static void Method1()
  {
   
//thread1.Abort();一句中的 Abort会引发异常System.Threading.ThreadAbortException,其异常作用,下面会讲解   
   try
   {
    
int i;
    
for(i=0;i<10;i++)
    {
     Console.WriteLine(
"Method1 at :" + i.ToString());  
     DelayTime(
1);  //延长时间(模拟执行任务)
    }
   }
   
catch(System.Threading.ThreadAbortException)
   {
    
//注意一点,线程跳出此语句块后才终止。
    
//这里可以写释放此进程占用的资源代码,或者其它一些操作,比如: 在进程结束前将重要数据写回数据库中
    Console.WriteLine("进程1马上将被强制杀死!"); 
    Thread.ResetAbort();  
//取消Abort()操作,我在这里加这句没用,反而出现异常了,读者如果知道,请告诉我怎样写才对   
   }
  }
  
public static void Method2()
  {
   
int i;
   
for(i=0;i<10;i++)
   {
    Console.WriteLine(
"Method2 at :" + i.ToString());  
    DelayTime(
1);  //延长时间,模拟执行任务
   }
  }
  
  
private static void DelayTime(int n)
  {
   DateTime startTime 
= DateTime.Now;
   
while(startTime.AddSeconds(n) > DateTime.Now)
   {
    
//延长时间,模拟实际中的进程
   }
  }

  [STAThread]
  
static void Main(string[] args)
  {              
   Thread thread1 
= new Thread(new ThreadStart(Method1));   
   Thread thread2 
= new Thread(new ThreadStart(Method2));   
   thread1.Start();
   thread2.Start();
   thread1.Abort(); 
//将线程强制终止(杀死)   
            
   
//thread1.Join的作用是无限制等待thread1终止后,才执行下面的语句,起到与主线程同步的作用.
   
//原因是: thread1最终是被终止的,但是thread1一个独立的线程,它并不会马上被终止。
   
//什么时候用:就拿这里来举例吧,当thread1占用着一个资源,当thread1终止后,
   
//thread2线程马上也要用此资源,这就要求等待thread1彻底终止并释放后占用资源后,才能接着执行下一句,
   
//否则线程thread2会找不到此资源,甚至会发生异常错误! 为了安全起见,一般是要在Abort()方法后面紧跟一个Join()方法的.
   
   
            
//thread1.Suspend();//此方法将线程无限制时间的挂起,相当于无限制时间的暂停线程
            
//thread1.Resume(); //将正在挂起的进程继续执行
   
   
//Thread.Sleep(1000);//暂停线程1秒钟,以毫秒为单位暂停.
   
   
//Thread.ResetAbort();     //取消Abort()操作
   
//thread1.Interrupt(); //中止线程现在处的状态。如果线程由运行转到休眠,执行此句后,会使线程重新返回到运行状态
            
   Console.Read();
  }
 }
}

 (八)线程
--借助 封装类 实现“线程调用带参方法”
(一).描述
      由于线程只能执行无参数方法. 有时候需要线程执行
"带参数方法"
      此示例演示怎样借助封装类实现“线程调用带参方法”
(二).代码
   
using System;
using System.Threading;

namespace 借助封装类实现_线程调用带参方法_
{
 
class Help
 {
  
public int x = 0;  //乘数1
  public int y = 0;  //乘数2
  public int end = 0//存放结果
 }
 
class MyClass
 {  
  
public static Help  myHelp = new Help();
        
          
  [STAThread]
  
static void Main(string[] args)
  { 
            
//给类的成员赋值
   myHelp.x = 5;
   myHelp.y 
= 10;                 
   
   Thread thread 
= new Thread(new ThreadStart(GetAccumulate));
            thread.Start();

   Thread.Sleep(
1000); //主线程等待子线程计算完成,否则取得的值为默认值 : 0
   
   Console.WriteLine(
"两数乘积结果为: "+myHelp.end.ToString());

   Console.Read();
   
  }

  
/// 
  
/// 得到两个整数的集
  
/// 

  
/// 乘数x
  
/// 乘数y
  
/// x*y
  public static void GetAccumulate()
  {
   myHelp.end 
= myHelp.x * myHelp.y;
  }
 }
}




posted @ 2007-07-24 20:41  hq5460  阅读(227)  评论(0编辑  收藏  举报