浅谈C#中的多线程编程[1]

  记录,做到温故而知新。

    一、相关概念:
  
什么是进程?
   当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。
  
什么是线程?
  
线程是程序中的一个执行流,每个线程都有自己的专有寄存器( 栈指针、程序计数器等) ,但代码区是共享的,即不同的线程可以执行同样的函数。
  
什么是多线程?
  
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

  多线程的好处:
  
可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
  
多线程编程有好处,也有不好的地方,如:
  
线程也是对象,需要占用内存,线程越多占用内存越多;
  
多线程需要协调和管理,所以需要CPU时间跟踪线程;
  
线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
  
线程太多会导致控制太复杂,最终可能带来产生Bug的风险。

   二、Thread类
  
先来理解下Thread类,这是实现多线程编程的基础。Thread类位于System.Threading命名空间,其构造函数为:
  
public Thread(ParameterrizedThreadStart start)
  public Thread(ThreadStart start)
  public Thread(ParameterizedThreadStart start, int maxStackSize)
  public Thread(ThreadStart start, int maxStackSize)
  这些构造函数涉及3种类型的参数:
  
1)ParameterizedThreadStart:是一个委托类型,表示此线程开始执行时要调用的方法,支持向调用的方法传递一个参数。
  
2)ThreadStart:是一个委托类型,表示此线程开始执行时要调用的方法没有参数的委托类型,不支持向调用的方法传递一个参数。
  
3)maxStackSize:表示线程要使用的最大堆栈大小,如果为0刚使用可执行文件的文件头中指定的默认最大堆栈大小。
  
Thread类有几个至关重要的方法,描述如下:
  
Start():启动线程;
  
Sleep(int):静态方法,暂停当前线程指定的毫秒数;
  Abort():通常使用该方法来终止一个线程;
  
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
  Resume():恢复被Suspend()方法挂起的线程的执行。

 

  Thread类基本的使用代码如下:
  
 

ContractedBlock.gif ExpandedBlockStart.gif View Code
using  System;
using  System.Threading;
namespace  ProgrammingCSharp4
{
    
public   class  Program
    {
        
public   static   void  Main( string [] args)
        {            
            Console.WriteLine(
" [主线程id:{0}] " ,Thread.CurrentThread.ManagedThreadId);
            Thread thread1 
=   new  Thread(Print);
            thread1.Start();
            Thread thread2 
=   new  Thread(PrintEx);
            thread2.Start(
" 测试 " );
            Console.ReadKey(
true );
        }
        
public   static   void  Print()
        {
            
int  threadId  =  Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine(
" [当前线程id:{0}]{1} " ,threadId,DateTime.Now.ToShortTimeString());
        }
        
public   static   void  PrintEx( object  obj)
        {
            
int  threadId  =  Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine(
" [当前线程id:{0}]{1} " ,threadId,obj);
        }
    }
}

  三、线程池的使用
  
C#中,我们可以通过一种叫做“池(Pool)”的技术来优化对象的使用,其原理是预先创建一定数量的对象放在“池”里,在对象被请求的时候,某个对象被从“池”中取出供使用,使用完毕再重新放回“池”中,等待下一次的请求。我们可以自己实现这样的线程池,也可以使用.NET Framework为我们所提供的线程池,它叫做TreadPool,位于System.Threading命名空间。
  
需要注意的是线程池中的线程均为后台线程,即它们的IsBackground属性为True。也就是说在所有的前台线程都已经退出后,ThreadPool中的线程不会让应用程序继续保持运行。
  
所以当我们执行一些简单的、耗时短暂的任务时,才应该使用到线程池,在下面的情况下则不应该使用线程池技术:
  
Ø 当需要创建一个前台线程时;
  
Ø 线程池中的线程都是默认优先级的,因此当需要创建具有特定优先级的线程时就不应该使用线程池;  
  
Ø 当需要某个任务只和特定的线程关联时,因为无法选择执行任务时使用的是哪一个具体的线程;
  
Ø 当需要中止特定的线程时不应使用线程池,它不提供这个功能;
  
Ø 线程执行时间比较长时;

  
要使用ThreadPool中的线程,需要使用TheadPool.QueueUserWorkItem这个静态方法指定线程要调用的方法,该方法有两个重载版本:
  
public static bool QueueUserWorkItem(WaitCallBack callBack)
  public static bool QueueUserWorkItem(WaitCallBack callBack,object state)
  WaitCallBack是一个委托类型,下面是线程池使用的例子:

ContractedBlock.gif ExpandedBlockStart.gif View Code
using  System;
using  System.Threading;
namespace  AsynchronousSample
{
    
class  Program
    {
        
public   static   void  Main( string [] args)
        {
            ThreadPool.QueueUserWorkItem(Counter);
            ThreadPool.QueueUserWorkItem(Counter,
" AsynchronousSample Test " );
            Console.WriteLine(
" [Thread ID = {0}]The main thread is started. " ,Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(
500 );
            Console.WriteLine(
" The main thread is closed. " ); 
            
            Console.ReadKey(
true );
        }
        
        
private   static   void  Counter( object  state)
        {
            Console.WriteLine(
" Counting begins, from 1 to 100: " );
            Console.WriteLine(
" the Parameter is:{0} " ,state);
            
for ( int  counter  =   0  ; counter  < 100 ;counter ++ )
            {
                
if ( null == state)
                {
                    Console.WriteLine(
" [Thread ID = {0}] {1} " ,Thread.CurrentThread.ManagedThreadId,counter);
                }
else
                {
                    Console.WriteLine(
" [Thread ID = {0}] {1} " ,Thread.CurrentThread.ManagedThreadId,state);
                }
                Thread.Sleep(
100 );
            }
        }
    }
}


  未完待续,下次接着复习Thread的相关属性与用法。

 

转载于:https://www.cnblogs.com/wpdev/archive/2011/03/09/1977763.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值