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

思绪由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

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

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

  1. 面试-JVM-类加载-类加载器--自定义类加载器-JVM调优

    文章目录 ==类加载== 谈谈你对类文件结构的理解?有哪些部分组成? 谈谈你对类加载机制的了解? 编写java代码是如何运行起来的? 类加载机制 类加载各阶段的作用分别是什么? 有哪些类加载器?分别有 ...

  2. 面试干货4——你对Java类加载器(自定义类加载器)有了解吗?

    类加载器 推荐:在准备面试的同学可以看看这个系列 一.类加载器的作用 二.Java虚拟机类加载器结构 1. 引导类(启动类)加载器 2. 扩展类加载器 3. 系统类加载器 三.类加载器的加载机制 1. ...

  3. java加载自己写的类_java 自定义类加载器从磁盘或网络加载类

    一.编写自定义类加载器类 package com.mybatis.entity; import java.io.ByteArrayOutputStream; import java.io.File; ...

  4. 马士兵java面试八股文及答案

    马士兵java面试八股文及答案 Java面向对象有哪些特征,如何应用 HashMap原理是什么,在jdk1.7和1.8中有什么区别 ArrayList和LinkedList有什么区别 高并发中的集合有 ...

  5. 2021秋招Java面试八股文让629人成功进入大厂,堪称2021最强

    前言 2021秋招即将来临,很多同学会问Java面试八股文有必要背吗? 我的回答是:很有必要.你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂. 国内的互联网面试,恐怕是现存的.最接近科举考 ...

  6. 【面试】前端面试八股文

    一.JS 1.使用 (1)标签引用 <script>alert("Hello,World!");</script> (2)文件引用 <script s ...

  7. 《面试八股文》之Dubbo17卷

    微信公众号:moon聊技术 关注选择" 星标 ", 重磅干货,第一 时间送达! [如果你觉得文章对你有帮助,欢迎关注,在看,点赞,转发] 前言 虽然金三银四过了,但是金九银十马上就 ...

  8. 现在人手必备Java面试八股文,从起跑线开始冲刺

    前言 2022秋招即将来临,很多同学会问Java面试八股文有必要背吗? 我的回答是:很有必要.你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂. 国内的互联网面试,恐怕是现存的.最接近科举考 ...

  9. 这份Java面试八股文让329人成功进入大厂,堪称2022最强

    前言 2022秋招即将来临,很多同学会问Java面试八股文有必要背吗? 我的回答是:很有必要.你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂. 国内的互联网面试,恐怕是现存的.最接近科举考 ...

最新文章

  1. 仿百度文库方案[openoffice.org 3+swftools+flexpaper](三) 之 使用JODConverter将office文档转换为pdf...
  2. 预训练后性能反而变差,自训练要取代预训练了吗?
  3. MSRA副院长周明博士:四大研究领域揭示自然语言技术的奥秘
  4. SD-WAN — Overview
  5. ABAP函数:SD_VBAP_READ_WITH_VBELN(根据销售订单读取表vbap中的信息)
  6. 鸿蒙大陆武器合成,鸿蒙大陆9.1攻略(附隐藏英雄密码)
  7. java 执行html里的js_如何用java执行指定页面中的js代码
  8. 题目 2055: 等待戈多(最短路)
  9. C#实践设计模式原则SOLID
  10. slqite3库查询数据处理方式_SQLite3命令操作大全
  11. vue自定义插件-弹框
  12. 网页中加载flash的方法
  13. intellij idea 中右键项目没有git
  14. 百度手机输入法,如何使用五笔98版?
  15. 华为手机计算机代码大全,华为手机指令代码大全,你想要了解的功能都在这里!...
  16. python结巴分词_Python中文分词工具之结巴分词用法实例总结【经典案例】
  17. linux救黑砖手机,手机黑砖9006/9008救砖教程 通用救砖模式详细流程
  18. 个人主页,引导页,导航网站源码三分钟下载安装【美观大气】
  19. Android获取系统字体的大小,修改android系统字体大小
  20. PMBOK项目管理知识体系指南—PMP项目管理学习笔记。

热门文章

  1. 下午去银行办理按揭手续,不得已调休半天
  2. 模块定义文件导出类_浓缩的就是精华——ES6模块精炼讲解
  3. 68.iOS设备尺寸及型号代码(iPhoneXR/XS)
  4. BZOJ.3265.志愿者招募加强版(费用流SPFA)
  5. NYOJ746 整数划分
  6. 基于'sessionStorage'与'userData'的类session存储
  7. 40个最好的Tumblr主题
  8. Mac OS使用技巧之二:修改变量Path解决android: command not found
  9. 后缀的形容词_构词法(18)构成形容词的常见后缀 3
  10. MySQL数据库的优化(下)MySQL数据库的高可用架构方案