多线程实战(三)线程池

创建线程是昂贵的操作,所有为每个短暂的异步操作创建线程会产生显著的开销。为了解决这种短暂的任务,我们把它交给线程池(pooling);线程池可以成功地适应任何需要大量短暂开销资源情况。我们事先分配一定的资源,将这些资源放入到资源池。每次需要新的资源,只需要从池中获取一个,而不是创建一个新的。当资源不在被使用,就将其返回到池中;

ThreadPool

异步

CancellationTokenSource 类

RegisterWaitForSingleObject

ThreadPool

1.创建线程池

  static void Main1(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            Console.ReadKey();
        }

        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

2.参数传递

 static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            ThreadPool.QueueUserWorkItem(AsyncOperation,"妹子");
            Console.ReadKey();
        }

        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

3.另外的写法

static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            ThreadPool.QueueUserWorkItem(AsyncOperation,"妹子");

            ThreadPool.QueueUserWorkItem(state =>
            {
                Console.WriteLine("参数状态: {0}", state);
                Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }, "妹子");

            Console.ReadKey();
        }

        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

异步

 static void Main()
        {
            int threadId = 0;
            RunOnThreadPool poolDelegate = Test1;
            IAsyncResult r = poolDelegate.BeginInvoke(out threadId, Callback1, "异步回调参数");
            string result = poolDelegate.EndInvoke(out threadId, r);
            Console.WriteLine(result);
            Console.ReadKey();
        }

        private delegate string RunOnThreadPool(out int threadId);

        private static void Callback1(IAsyncResult ar)
        {
            Console.WriteLine("开始回调");
            Console.WriteLine("传入回掉的值: {0}", ar.AsyncState);
            Console.WriteLine("回掉是否是托管线程池: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Console.WriteLine("线程iD: {0}", Thread.CurrentThread.ManagedThreadId);
        }

        private static string Test1(out int threadId)
        {
            Console.WriteLine("开始异步...");
            Console.WriteLine("是否是托管线程池: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return string.Format("池中线程ID: {0}", threadId);
        }

异步回调也是输入托管线程池

CancellationTokenSource 类

通知 CancellationToken,告知其应被取消。

static void Main(string[] args)
        {
            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation3(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            Thread.Sleep(TimeSpan.FromSeconds(2));

            Console.ReadKey();
        }

        static void AsyncOperation1(CancellationToken token)
        {
            Console.WriteLine("Starting the first task");
            for (int i = 0; i < 5; i++)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("The first task has been canceled.");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("The first task has completed succesfully");
        }

        static void AsyncOperation2(CancellationToken token)
        {
            try
            {
                Console.WriteLine("Starting the second task");

                for (int i = 0; i < 5; i++)
                {
                    token.ThrowIfCancellationRequested();
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
                Console.WriteLine("The second task has completed succesfully");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("The second task has been canceled.");
            }
        }

        private static void AsyncOperation3(CancellationToken token)
        {
            bool cancellationFlag = false;
            token.Register(() => cancellationFlag = true);
            Console.WriteLine("Starting the third task");
            for (int i = 0; i < 5; i++)
            {
                if (cancellationFlag)
                {
                    Console.WriteLine("The third task has been canceled.");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("The third task has completed succesfully");
        }

RegisterWaitForSingleObject

RegisterWaitForSingleObject提供了一些简单的线程间交互

static void Main(string[] args)
        {
            RunOperations(TimeSpan.FromSeconds(5));
            RunOperations(TimeSpan.FromSeconds(7));
            Console.ReadKey();
        }

        static void RunOperations(TimeSpan workerOperationTimeout)
        {
            using (var evt = new ManualResetEvent(false))
            using (var cts = new CancellationTokenSource())
            {
                Console.WriteLine("注册超时行为...");
                var worker = ThreadPool.RegisterWaitForSingleObject(evt,
                    (state, isTimedOut) => WorkerOperationWait(cts, isTimedOut), null, workerOperationTimeout, true);

                Console.WriteLine("启动长时间运行...");

                ThreadPool.QueueUserWorkItem(_ => WorkerOperation(cts.Token, evt));

                Thread.Sleep(workerOperationTimeout.Add(TimeSpan.FromSeconds(2)));
                worker.Unregister(evt);
            }
        }

        static void WorkerOperation(CancellationToken token, ManualResetEvent evt)
        {
            for(int i = 0; i < 6; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            evt.Set();
        }

        static void WorkerOperationWait(CancellationTokenSource cts, bool isTimedOut)
        {
            if (isTimedOut)
            {
                cts.Cancel();
                Console.WriteLine("超时取消.");
            }
            else
            {
                Console.WriteLine("操作成功.");
            }
        }

时间: 2024-10-08 10:17:33

多线程实战(三)线程池的相关文章

Android多线程编程之线程池学习篇(一)

Android多线程编程之线程池学习篇(一) 一.前言 Android应用开发中多线程编程应用比较广泛,而应用比较多的是ThreadPoolExecutor,AsyncTask,IntentService,HandlerThread,AsyncTaskLoader等,为了更详细的分析每一种实现方式,将单独成篇分析.后续篇章中可能涉及到线程池的知识,特此本篇分析为何使用线程池,如何使用线程池以及线程池的使用原理. 二.Thread Pool基础 进程代表一个运行中的程序,一个运行中的Android

多线程系列(2)线程池ThreadPool

上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止,显然是很麻烦的一件事情.还好.net framework为我们提供了线程池ThreadPool来帮助我们来管理这些线程,这样我们就不再需要手动地去终止这些线程.这一篇文章就让我们来学习一下线程池ThreadPool吧.关于它我想从以下几个方面进行总结. 认识线程池ThreadPool Thread

JAVA多线程(三) 线程池和锁的深度化

github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/src/main/java/com/kawa/thread 1.线程池 1.1 线程池是什么 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务

Java多线程系列--“JUC线程池”04之 线程池原理(三)

本章介绍线程池的生命周期. 线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态.线程池也有5种状态:然而,线程池不同于线程,线程池的5种状态是:Running, SHUTDOWN, STOP, TIDYING, TERMINATED. 线程池状态定义代码如下: /** * The main pool control state, ctl, is an atomic integer packing * two conceptual fields * workerCount, indi

Java多线程-新特性-线程池

Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要. 有关Java5线程新特征的内容全部在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程.目前有关这方面的资料和书籍都少之又少,大部分介绍线程方面书籍还停留在java5之前的知识层面上. 在Java5之

Java多线程设计模式(4)线程池模式

前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将“委托消息的一端”和“执行消息的一端”用两个不同的线程来实现.该线程模式主要包括三个部分: 1,Request参与者(委托人),也就是消息发送端或者命令请求端 2,Host参与者,接受消息的请求,负责为每个消息分配一个工作线程. 3,Worker参与者,具体执行Request参与者的任务的线程,由Host参与者来启动. 由于常规调用一个方法后,必须等待该方法完全执行完毕

【多线程】设置线程池线程数量

一.需求        Web-Server通常有个配置,最大工作线程数,后端服务一般也有个配置,工作线程池的线程数量,这个线程数的配置不同的业务架构师有不同的经验值,有些业务设置为CPU核数的2倍,有些业务设置为CPU核数的8倍,有些业务设置为CPU核数的32倍.“工作线程数”的设置依据是什么,到底设置为多少能够最大化CPU性能. 二.一些共性认知        在进一步深入讨论之前,先以提问的方式就一些共性认知达成一致.        提问:工作线程数是不是设置的越大越好?        回

Java多线程系列--“JUC线程池”03之 线程池原理(二)

线程池示例 在分析线程池之前,先看一个简单的线程池示例. import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolDemo1 { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThre

C#多线程学习 之 线程池[ThreadPool](转)

在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPool(线程池)来解决: 另一种情况:线程平时都处于休眠状态,只是周期性地被唤醒                   这一般使用Timer(定时器)来解决: 本篇文章单单讲线程池[ThreadPool] ThreadPool类 MSDN帮助信息: http://msdn.microsoft.com/z

Java多线程18:线程池

使用线程池与不使用线程池的差别 先来看一下使用线程池与不适应线程池的差别,第一段代码是使用线程池的: public static void main(String[] args) { long startTime = System.currentTimeMillis(); final List<Integer> l = new LinkedList<Integer>(); ThreadPoolExecutor tp = new ThreadPoolExecutor(100, 100