ThreadPool执行异步操作

简介: 使用ThreadPool_类执行异步任务 /* ThreadPool 类是一个静态类型类,使用ThreadPool 类执行异步时通常调用ThreadPool 的 QueueUserWorkItem 方法,这个方法有一个重载版本,如下:public static bool ...


使用ThreadPool_类执行异步任务


/*
 ThreadPool 类是一个静态类型类,使用ThreadPool 类执行异步时通常调用ThreadPool 的 QueueUserWorkItem 方法,这个方法有一个重载版本,如下:

public static bool QueueUserWorkItem(WaitCallback callBack);
       
public static bool QueueUserWorkItem(WaitCallback callBack, object state);

QueueUserWorkItem 方法接受一个WaitCallback 类型的委托作为回调方法以及可以选择传递一个线程池线程执行回调方法时所需要的数据对象。

WaitCallback 委托类型的定义如下:

public delegate void WaitCallback(object state);

线程池的QueueUserWorkItem方法在调用以后会立即返回,所传递的回调方法会有以后线程池线程执行。使用线程池线程执行异步任务代码如下:
 
 
 */


示例如下:



namespace 使用ThreadPool_类执行异步任务
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始执行任务,线程ID:{0}",Thread.CurrentThread .ManagedThreadId);
            //使用ThreadPool.QueueUserWorkItem方法将一个异步任务添加到线程池任务队列中,
            //可以为线程池线程执行方法时传递一个数据对象
            //如果不需要传递数据uk恶意使用QueueUserWorkerItem只有WaitCallback一个参数类型的版本
            //或传递null
            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("线程池线程开始执行异步任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId );
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);

                }
            
            },null );

            Console.WriteLine("主线程执行其他任务。线程ID:{0}",Thread .CurrentThread .ManagedThreadId );

            //使调用线程睡眠2000毫秒,等待线程池执行完成
            Thread.Sleep(2000);
            Console.WriteLine("主线程继续执行任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId);

        }
    }
}







线程池对线程的管理



/*
 CLR允许开发人员设置线程池需要创建的最大和最小工作者线程和IO线程,但是最好不要设置线程池的线程数,CLR对线程池的工作者线程和I/O线程的最大线程数设置了1000的默认值。我们可以使用线程池的如下方法对线程池数进行设置和获得最大线程池数和当前运行线程数之间的差值
 * 
 * //设置可以同时处于活动状态的线程池的请求数目。
// 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
 // 发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。   
public static bool SetMinThreads(int workerThreads, int completionPortThreads);
 //检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
 public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);
//发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
 public static void GetMinThreads(out int workerThreads, out int completionPortThreads);

 //获得最大线程池线程数和当前运行线程数之间的差值。
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);
 
 
 */


示例代码:


namespace 线程池对线程的管理
{
    class Program
    {
        static void Main(string[] args)
        {
            int worker, io;

            //获得线程池默认的最大线程数目。
            ThreadPool.GetMaxThreads(out worker ,out io);

            Console.WriteLine("1,CLR线程池默认最大线程数据,工作者线程数:{0},IO线程数:{1}",worker ,io );

            //设置线程池最大线程数
            ThreadPool.SetMaxThreads(100,100);
            ThreadPool.QueueUserWorkItem(state => {

                Thread.Sleep(2000);
                Console.WriteLine("4,线程池线程开始执行异步任务。线程ID:{0},",Thread.CurrentThread .ManagedThreadId );

            
            });

            Console.WriteLine("2,自定义设置线程池默认最大线程数据后,工作者线程数:{0},IO线程数: {1}:",worker ,io );
            //获得最大线程池线程数和当前运行线程数之间的差值
            ThreadPool.GetAvailableThreads(out worker ,out io );
            Console.WriteLine("3,获得最大线程池线程数和当前运行线程数之间的差值,工作者线程: {0},IO线程: {1}",worker ,io );
            Console.ReadKey();



        }
    }
}













/*
 
 线程池中的工作者线程是许多异步计算任务锁使用的线程,在线程池内部,工作者线程采用先入先出的算法将工作项从线程的全家队列中取出工作项并执行任务。在同一时刻可能有多个工作者线程从全局队列中取出工作项,因此所有工作者线程都会竞争一个线程同步锁,以保证两个或更多工作者线程不会在同一时刻取出工作项。
 * 
 * 
 * 线程池在创建工作者线程时,默认会创建ThreadPool.setminthreads方法锁设置的值。如果没有设置这个值,就会创建应用程序进程允许的使用的CUP数相同的工作者线程,这些工作这线程简史线程池任务的执行情况,得以动态的创建更多的或销毁空闲线程。
 * 
 
 */



线程执行上下文的流动





/*
 每个线程都有一个执行上下文,执行上下文包含了安全设置,宿主设置和逻辑调用上下文数据,CLR默认是把初始线程的执行上下文数据向辅助线程流动,初始线程在收集和复制执行上下文数据并传递到辅助线程时会带来性能的损失。如果不需要这些执行上下文数据可以使用system.threading.executioncontext类组织执行上下文数据的流转。
 * 常用方法::::::::::::
 * 
 *         //     指示当前是否取消了执行上下文的流动。
        public static bool IsFlowSuppressed();
        //     恢复执行上下文在异步线程之间的流动。
        public static void RestoreFlow();
       //取消执行上下文在异步线程之间的流动。
        public static AsyncFlowControl SuppressFlow();

 
 
 
 
 */
namespace 线程执行上下文的流动
{
    class Program
    {
        static void Main(string[] args)
        {
            //把对象存储在调用逻辑上下文中,并将该对象与指定名称相关联
            System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("key","这是主线程的执行上下文数据");

            Console.WriteLine("主线程执行上下文数据:{0}",System.Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            //阻止主线程执行上下文数据的传递
            ExecutionContext.SuppressFlow();  //取消执行上下文在异步线程直接的流动
            Console.WriteLine("调用suppressFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());



            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据被阻止传递:{0}",System .Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            
            });  //这里是没有输出的

            //恢复主线程执行上下文数据的传递
            ExecutionContext.RestoreFlow();//回复执行上下文在异步线程上的流动
            Console.WriteLine("调用RestoreFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());

            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据没有被阻止传递:{0}",System.Runtime.Remoting .Messaging .CallContext .LogicalGetData ("key"));

            
            
            });//将方法排入队列以便执行

            Console.ReadKey();


        }
    }
}





目录
相关文章
|
6月前
|
Java 调度
线程的yield操作
线程的yield操作的作用是让出目前正在执行的线程放弃当前的执行,让出CUP权限,使得CPU去执行其他的线程。处于让步状态的JVM层面的线程状态仍然是RUNNABLE状态,但是该线程所对应的操作系统层面的线程从状态上来说会从执行状态编程就绪状态。线程yield时,线程放弃和重占CPU的时间是不确定的,可能是刚刚放弃CPU,马上又获得CPU执行权限,重新开始执行。
27 0
|
22天前
|
Java
使用线程池异步执行
使用线程池异步执行
13 0
|
1月前
|
存储 Java
什么是线程池,线程池的状态,线程池的用法示例
什么是线程池,线程池的状态,线程池的用法示例
|
3月前
|
Java
Future:异步任务结果获取
Future:异步任务结果获取
39 0
|
5月前
主线程等待子线程执行完毕再执行方法
主线程等待子线程执行完毕再执行方法
|
10月前
|
Java
【java】主线程等待子线程执行结束后再执行,线程池
【java】主线程等待子线程执行结束后再执行,线程池
138 0
|
12月前
|
消息中间件 JavaScript 小程序
线程池执行的用户任务抛出异常会怎样
线程池执行的用户任务抛出异常会怎样
|
Java 调度
多线程执行顺序以及run方法的调用
多线程执行顺序以及run方法的调用
多线程执行顺序以及run方法的调用
|
Java Spring 容器
你知道 @Async 是怎么让方法异步执行的吗?
@Async 是通过注解标记来开启方法的异步执行的;对于注解的底层实现,除了 java 原生提供那种依赖编译期植入的之外,其他的基本都差不多,即运行时通过反射等方式拦截到打了注解的类或者方法,然后执行时进行横切拦截;另外这里还有一个点就是方法异步执行,所以对于 @Async 的剖析,就一定绕不开两个基本的知识点,就是代理和线程池。 在了解到这些之后,我们来拆解下 @Async 的基本原理。
166 0
你知道 @Async 是怎么让方法异步执行的吗?
|
Java
切记【阻塞/非阻塞】【FutureTask异步执行】
切记【阻塞/非阻塞】【FutureTask异步执行】
107 0