面试八股文:你写过自定义任务调度器吗?

最近入职了新公司,尝试阅读祖传代码,记录并更新最近的编程认知。

思绪由Q1引发,后续Q2、Q3基于Q1的发散探究

Q1. Task.Run、Task.Factory.StartNew 的区别?

我们常使用Task.RunTask.Factory.StartNew创建并启动任务,但是他们的区别在哪里?在哪种场景下使用前后者?

官方推荐使用Task.Run方法启动基于计算的任务, 当需要对长时间运行、基于计算的任务做精细化控制时使用Task.Factory.StartNew。

Task.Factory提供了自定义选项、自定义调度器的能力,这也说明了Task.Run是Task.Factory.StartNew的一个特例,Task.Run 只是提供了一个无参、默认的任务创建和调度方式。

当你在Task.Run传递委托

Task.Run(someAction);

实际上等价于

Task.Factory.StartNew(someAction, 
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

一个长时间运行的任务,如果使用Task.Run铁定会使用线程池线程,可能构成滥用线程池线程,这个时候最好在独立线程中执行任务。

Q2. 既然说到Task.Run使用线程池线程,线程池线程有哪些特征?为什么有自定义调度器一说?

github: TaskScheduler[1] 251行显示TaskScheduler.Dafult确实是线程池任务调度器。

线程池[2]线程的特征:
① 池中线程都是后台线程
② 线程可重用,一旦线程池中的线程完成任务,将返回到等待线程队列中, 避免了创建线程的开销
③ 池中预热了工作者线程、IO线程

我启动一个脚手架项目:默认最大工作者线程32767,最大IO线程1000 ; 默认最小工作线程数、最小IO线程数均为8个

github: ThreadPoolTaskScheduler[3] 显示线程池任务调度器是这样调度任务的:

/// <summary>
/// Schedules a task to the ThreadPool.
/// </summary>
/// <param name="task">The task to schedule.</param>
protected internal override void QueueTask(Task task)
{TaskCreationOptions options = task.Options;if ((options & TaskCreationOptions.LongRunning) != 0){// Run LongRunning tasks on their own dedicated thread.Thread thread = new Thread(s_longRunningThreadWork);thread.IsBackground = true; // Keep this thread from blocking process shutdownthread.Start(task);}else{// Normal handling for non-LongRunning tasks.bool preferLocal = ((options & TaskCreationOptions.PreferFairness) == 0);ThreadPool.UnsafeQueueUserWorkItemInternal(task, preferLocal);}
}

请注意8-14行:若上层使用者将LongRunning任务应用到默认的任务调度器(也即ThreadPoolTaskScheduler),ThreadPoolTaskScheduler会有一个兜底方案:会将任务放在独立线程上执行。

何时不使用线程池线程

有几种应用场景,其中适合创建并管理自己的线程,而非使用线程池线程:

•需要一个前台线程。•需要具有特定优先级的线程。•拥有会导致线程长时间阻塞的任务。线程池具有最大线程数,因此大量被阻塞的线程池线程可能会阻止任务启动。•需将线程放入单线程单元。所有 ThreadPool 线程均位于多线程单元中。•需具有与线程关联的稳定标识,或需将一个线程专用于一项任务。

Q3. 既然要自定义任务调度器,那我们就来倒腾?

实现TaskScheduler 抽象类,其中的抓手是“调度”,也就是 QueueTask、TryExecuteTask 方法,之后你可以自定义数据结构和算法, 从数据结构中调度出任务执行。

给个例子:

public sealed class CustomTaskScheduler : TaskScheduler, IDisposable{private BlockingCollection<Task> tasksCollection = new BlockingCollection<Task>();private readonly Thread mainThread = null;public CustomTaskScheduler(){mainThread = new Thread(new ThreadStart(Execute));if (!mainThread.IsAlive){mainThread.Start();}}private void Execute(){foreach (var task in tasksCollection.GetConsumingEnumerable()){TryExecuteTask(task);}}protected override IEnumerable<Task> GetScheduledTasks(){return tasksCollection.ToArray();}protected override void QueueTask(Task task){if (task != null)tasksCollection.Add(task);           }protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued){return false;}private void Dispose(bool disposing){if (!disposing) return;tasksCollection.CompleteAdding();tasksCollection.Dispose();}public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}}

引用链接

[1] github: TaskScheduler: https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs
[2] 线程池: https://docs.microsoft.com/en-us/dotnet/standard/threading/the-managed-thread-pool
[3] github: ThreadPoolTaskScheduler: https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs

更多干货及最佳实践分享
关注并星标我们

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302670.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速掌握MATLAB应用,从这一步开始

有人说&#xff0c;“MATLAB除了不会生孩子&#xff0c;什么都会。”矩阵运算、数据可视化、GUI&#xff08;用户界面&#xff09;设计、甚至是连接其他编程语言&#xff0c;MATLAB都能轻松实现&#xff01;那么&#xff0c;MATLAB到底有多厉害&#xff1f;MATLAB拥有丰富的算法…

Solarwinds的NetFlow Traffic Analyzer中的Cisco设备配置

如果要使用Solarwinds的NetFlow Traffic Analyzer这个产品首先要安装Orion然后再安装Netflow&#xff0c;其次要设备支持Netflow&#xff0c;下面列出的是支持netflow的cisco设备&#xff1a;支持cisco netflower的cisco设备2007-08-16 15:09 Cisco 800, 1700, 1800, 2800, 380…

mobile.php discuz,电脑访问discuz手机版【触屏版跳转标准版的修改方法】

推荐方法&#xff1a;以前我们介绍过如何通过修改Chrome浏览器运行参数的方法来模拟手机访问网站&#xff0c;但是在Chrome 32和33版本以后增加了更加便捷的方法&#xff0c;在开发者工具中只需要设置一下就能方便的模拟各种手机型号的访问效果了。方法如下&#xff1a;1、打开…

深入探究ASP.NET Core读取Request.Body的正确方式

前言相信大家在使用ASP.NET Core进行开发的时候&#xff0c;肯定会涉及到读取Request.Body的场景&#xff0c;毕竟我们大部分的POST请求都是将数据存放到Http的Body当中。因为笔者日常开发所使用的主要也是ASP.NET Core所以笔者也遇到这这种场景&#xff0c;关于本篇文章所套路…

送给“苦逼”的IT人系列1:IT人的“钱”景以及收入的两道坎

虽然IT工作五花八门&#xff0c;而且年纪有老有少&#xff0c;但IT人的收入总体还是比较有规律的&#xff0c;很明显的可以看出有两道坎&#xff0c;分别是10W&#xff0c;和30W&#xff0c;当然&#xff0c;我说的是年薪&#xff0c;是RMB&#xff0c;不包含任何跟销售相关的提…

追MM的各种算法

全世界有3.14 % 的人已经关注了数据与算法之美动态规划基本上就是说&#xff1a;你追一个MM的时候&#xff0c;需要对该MM身边的各闺中密友都好&#xff0c;这样你追MM这个问题就分解为对其MM朋友的问题&#xff0c;只有把这些问题都解决了&#xff0c;最终你才能追到MM。因此&…

gRPC在C#中的未来属于grpc-dotnet

作者&#xff1a;Jan Tattermuschgrpc-dotnet&#xff08;Grpc.Net.Client[1]和Grpc.AspNetCore.Server[2] nuget 包&#xff09;现在是.NET/C#中推荐的 gRPC 实现。最初的 gRPC C#实现&#xff08;Grpc.Core nuget 包&#xff09;将进入维护模式&#xff0c;不会得到任何新功能…

(部分来自windows核心编程)远程注入dll

{//仅仅支持ANSI路径//find the wndHWND hwnd FindWindow(NULL,"1.txt - 记事本");//get pidDWORD tid,pid;tid GetWindowThreadProcessId(hwnd,&pid);if (0pid)//for test{pid GetCurrentProcessId();}HANDLE hProcess OpenProcess(PROCESS_ALL_ACCESS,FALS…

linux命令apprw,linux命令学习1(示例代码)

[[email protected] app]# cat /etc/redhat-releaseCentOS Linux release 7.1.1503 (Core)总用量 2636-rw-r--r--. 1 root root 1222783 10月 28 12:09 Glances-1.7.1.tar.gz-rw-r--r--. 1 root root 388499 11月 7 13:20 htop-1.0.2.tar.gz-rw-r--r--. 1 root root 1081874 …

ML.NET 示例:对象检测

ML.NET 版本API 类型状态应用程序类型数据类型场景机器学习任务算法v1.4动态API最新控制台应用程序图像文件对象检测深度学习Tiny Yolo2 ONNX 模型有关如何构建此应用程序的详细说明&#xff0c;请参阅Microsoft Docs网站上附带的教程。问题对象检测是计算机视觉中的一个经典问…

双十一来了,揭秘菜鸟物流背后的那些算法黑科技

又是一年双十一&#xff0c;又一个巨大的挑战摆在了包括菜鸟网络在内的物流面前&#xff0c;但随着人工智能、大数据的应用越来越广泛&#xff0c;无人化仓储、无人化配送越来越多&#xff0c;供应链越来越扁平化&#xff0c;各种算法应用到物流领域的每一个细节。那么&#xf…

socket编程资料-网络收集

1、什么是Socket&#xff1f; Socket又称之为“套接字”&#xff0c;是系统提供的用于网络通信的方法。它的实质并不是一种协议&#xff0c;没有规定计算机应当怎么样传递消息&#xff0c;只是给程序员提供了一个发送消息的接口&#xff0c;程序员使用这个接口提供的方法&#…

linux监听端口丢失,linux – 如果没有监听端口,则为Systemd重启服务

我建议你采用不同的方法,并使用专用的监控工具来实现这一目标.我最喜欢的监控工具,允许重新启动服务,以防它们崩溃,或者不再在其配置的端口上监听,这是monit&#xff1a;https://packages.debian.org/jessie/monit配置文件中有很多示例,在此站点和其他地方有关设置的示例.我将列…

开源推荐:Asp.Net Core入门学习手册!

前言推荐一个入门级的.NET Core开源项目&#xff0c;非常适合新手入门学习.NET Core。开源地址:https://github.com/windsting/little-aspnetcore-book。手册在线下载地址&#xff1a;https://nbarbettini.gitbooks.io/little-asp-net-core-book/content/chapters/mvc-basics/c…

如何拿到高薪数据分析师offer?从精准解读一篇招聘信息开始!

大家好&#xff0c;我是大鹏&#xff0c;目前是一名数据分析师&#xff0c;从非本专业成功转行&#xff0c;创立“数据团学社”“城市数据研习社”&#xff0c;运营数十万人社群&#xff0c;联合发起“城市数据团”。最近有很多学弟学妹咨询我入行数据分析师的情况。总体上说&a…

微软翻译api的使用介绍和注意事项

google翻译api已经收费了&#xff0c;而微软翻译api目前是免费的&#xff0c;支持几种不同的方式访问&#xff0c;如果感兴趣可以自己封装下协议处理。官方介绍&#xff1a; http://msdn.microsoft.com/en-us/library/hh454950.aspx。 这里介绍一下java下的使用。Java下使用微软…

linux备份文件到ftp上,Linux服务器下用FTP上传下载备份文件

从linux服务器批量上传/home/test文件夹里面文件到FTP(192.168.1.122)里面wwwroot目录##shell脚本如下&#xff1a;updir/home/testtodirwwwrootip192.168.1.122usertestpasswordtest123123sssfind $updir -type d -printf $todir/’%P\n’| awk ‘{if ($0 “”)next;print “…

简单概述 .NET Framework 各版本区别

目前已发行的版本有1.0、1.1、2.0、3.0、3.5、4.0、4.5&#xff08;及4.5.1、4.5.2&#xff09;、4.6&#xff08;及4.6.1&#xff09;。1.0版本&#xff1a;最初的.net framework版本&#xff0c;作为一个独立的工具包存在。1.1版本&#xff1a;是1.1的升级版本&#xff0c;加…

为什么不能除以零?

全世界有3.14 % 的人已经关注了数据与算法之美如果你问苹果手机上的Siri&#xff0c;“零除以零等于多少”&#xff0c;它会显示&#xff1a;但是&#xff0c;英文版的Siri还会用语音说这一段话&#xff1a;“假如你有0块饼干&#xff0c;要分给0个朋友&#xff0c;每个人能分到…

设计模式之Builder

2019独角兽企业重金招聘Python工程师标准>>> Builder模式定义&#xff1a; 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们…