C#(ThreadPool)线程池的详解及使用范例

此文章是根据乌班图ysm的博客修改的,并加入了自己的一些见解

       线程和线程池都是进行多线程操作的,线程池是用来保存线程的一个容器,在程序创建线程来执行任务的时候线程池才会初始化一个线程,线程在执行完毕之后并不会被销毁,而是被挂起等待下一个任务的到来被激活执行任务,当线程池里的线程不够用的时候会新实例化一个线程,来执行,线程池里的线程会被反复利用。

       这和我们打客服电话是一个相似的场景,每个打电话的人是一个任务,每个话务员就像一个线程,话务员处理完一个任务之后并不会被辞退,而是等待下一个任务的到来。如果使用线程来处理问题,就相当于话务员处理完一个任务之后就被辞退了,新任务来的时候就再招聘一个。招聘话务员是要耗费资源的。大概就是这个意思。

范例1:获取线程池的相关信息与线程池运行范例

//存放要计算的数值的字段
public static double num1=-1;
public static double num2=-1;

static void Main(string[] args)
{
    //获取线程池的最大的线程数和维护的最小线程数
    int maxThreadNum,portThreadNum,minThreadNum;
    ThreadPool.GetMaxThreads(out maxThreadNum,out portThreadNum);
    ThreadPool.GetMinThreads(out minThreadNum,out portThreadNum);
    Console.WriteLine("最大线程数:{0}",maxThreadNum);
    Console.WriteLine("最小空闲线程数:{0}",minThreadNum);

    //函数变量值
    int x=15600;
    //启动第一个任务:计算x的8次方
    Console.WriteLine("启动第一个任务:计算{0}的8次方.",x);
    ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc1),x);
    //启动第二个任务
    Console.WriteLine("启动第二个任务:计算{0}的8次方",x);
    ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc2),x);
    //等待,直到两个数值等完成计算
    while(num1==-1||num2==-1);
    //打印计算结果
    Console.WriteLine("y({0})={1}",x,num1+num2);
}


private void TaskProc2(object state)
{
    num1=Math.Pow(Convert.ToDouble(state),8);
}

private void TaskProc1(object state)
{
    num2=Math.Pow(Convert.ToDouble(state),8);
}

2.退出线程池的执行

static void Main(string[] args)
{
    CancellationTokenSource cts=new CancellationTokenSource();
    ThreadPool.QueueUserWorkItem(t=>Counts(cts.Token,1000));
    Console.WriteLine("Press Any Key to cancel the operation");
    Console.ReadLine();
    cts.Cancel();
    Console.ReadLine();
}
private void Counts(CancellationToken token,int CountTo)
{
    for(int count=0;count<CountTo;count++)
    {
        if(token.IsCancellationRequested)
        {
            Console.WriteLine("Count is cancelled");
            break;
        }
        Console.WriteLine(count);
        Thread.Sleep(200);
    }
    Console.WriteLine("Count is stopped");
}

3.比较线程池和线程的执行效率

static void Main(string[] args)
{
    Stopwatch sw=new Stopwatch();
    sw.Start();
    for(int i=0;i<1000;i++)
    {
        Thread th=new Thread(()=>
        {
            int count=0;
            count++;
        });
        th.Start();
    }
    sw.Stop();
    Console.WriteLine("运行创建线程所需要的时间"+sw.ElapsedMilliseconds);
    sw.Restart();
    for(int i=0;i<1000;i++)
    {
        ThreadPool.QueueUserWorkItem(t=>
        {
            int count=0;
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            count++;
        })
    }
    sw.Stop();
    Console.WriteLine("运行线程池所需要花费的时间:"+sw.ElapsedMilliseconds);
}

4.线程池参数传递执行

static void Main(stirng[] args)
{
    //实例化类的对象
    ThreadDemoClass demoClass=new ThreadDemoClass();
    //WaitCallBack:是一个委托类型,表示要执行的方法
    //使用委托绑定线程池要执行的方法(无参数)
    WaitCallback wc1=demoClass.Run1;
    //将方法排入队列,在线程池变为可用时执行
    ThreadPool.QueueUserWorkItem(wc1);

    //使用委托绑定线程要执行的方法(带参数)
    WaitCallback wc2=new WaitCallback(demoClass.Run1);
    //将方法排入队列,在线程池变为可用执行
    ThreadPool.QueueUserWorkItem(wc2,"cdc");

    UserInfor userInfor=new UserInfor();
    userInfor.Name="cdc";
    userInfor.Age=36;
    
    //使用委托绑定线程池要执行的方法(有参数,自定义类型的参数)
    WaitCallback wc3=new WaitCallback(demoClass.Run2);
    //将方法排入队列,在线程池变为可用时执行
    ThreadPool.QueueUserWorkItem(wc3,userInfor);
    Console.WriteLine();
    Console.WriteLine("Main thread working...");
    Console.WriteLine("Main thread ID is:"+Thread.CurrentThread.ManagedThreadId);
}


internal calss UserInfor
{
    public Age{get;internal set;}
    public string{get;internal set;}
}

internal calss ThreadDemoClass
{
    public void Run1(object obj)
    {
        string name=obj as string;
        Console.WriteLine("Child thread working...");
        Console.WriteLine("My name is "+name);
        Console.WriteLine("Child thread ID is:"+Thread.CurrentThread.ManagedThreadId);
    }

    public void Run2(object obj)
    {
        UserInfor userInfor=(UserInfor)obj;
        Console.WriteLine("Child thread working...");
        Console.WriteLine("My name is "+userInfor.Name+",my age"+userInfor.Age);
        Console.WriteLine("Child thread ID is: "+Thread.CurrentThread.ManagedThreadId.ToString());
    }
}

 

上一篇:java 手写线程池


下一篇:如何管理默认的Java SwingWorker线程池?