偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試八股文:你寫過自定義任務(wù)調(diào)度器嗎?

企業(yè)動(dòng)態(tài)
我們常使用Task.Run和Task.Factory.StartNew創(chuàng)建并啟動(dòng)任務(wù),但是他們的區(qū)別在哪里?在哪種場景下使用前后者?

[[397412]]

本文轉(zhuǎn)載自微信公眾號(hào)「全棧碼農(nóng)畫像」,作者小碼甲。轉(zhuǎn)載本文請(qǐng)聯(lián)系全棧碼農(nóng)畫像公眾號(hào)。

最近入職了新公司,嘗試閱讀祖?zhèn)鞔a,記錄并更新最近的編程認(rèn)知。

思緒由Q1引發(fā),后續(xù)Q2、Q3基于Q1的發(fā)散探究

Q1. Task.Run、Task.Factory.StartNew 的區(qū)別?

我們常使用Task.Run和Task.Factory.StartNew創(chuàng)建并啟動(dòng)任務(wù),但是他們的區(qū)別在哪里?在哪種場景下使用前后者?

官方推薦使用Task.Run方法啟動(dòng)基于計(jì)算的任務(wù), 當(dāng)需要對(duì)長時(shí)間運(yùn)行、基于計(jì)算的任務(wù)做精細(xì)化控制時(shí)使用Task.Factory.StartNew。

Task.Factory提供了自定義選項(xiàng)、自定義調(diào)度器的能力,這也說明了Task.Run是Task.Factory.StartNew的一個(gè)特例,Task.Run 只是提供了一個(gè)無參、默認(rèn)的任務(wù)創(chuàng)建和調(diào)度方式。

當(dāng)你在Task.Run傳遞委托

  1. Task.Run(someAction); 

實(shí)際上等價(jià)于

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

一個(gè)長時(shí)間運(yùn)行的任務(wù),如果使用Task.Run鐵定會(huì)使用線程池線程,可能構(gòu)成濫用線程池線程,這個(gè)時(shí)候最好在獨(dú)立線程中執(zhí)行任務(wù)。

Q2. 既然說到Task.Run使用線程池線程,線程池線程有哪些特征?為什么有自定義調(diào)度器一說?

github: TaskScheduler[1] 251行顯示TaskScheduler.Dafult確實(shí)是線程池任務(wù)調(diào)度器。

線程池[2]線程的特征:

① 池中線程都是后臺(tái)線程

② 線程可重用,一旦線程池中的線程完成任務(wù),將返回到等待線程隊(duì)列中, 避免了創(chuàng)建線程的開銷

③ 池中預(yù)熱了工作者線程、IO線程

我啟動(dòng)一個(gè)腳手架項(xiàng)目:默認(rèn)最大工作者線程32767,最大IO線程1000 ; 默認(rèn)最小工作線程數(shù)、最小IO線程數(shù)均為8個(gè)

github: ThreadPoolTaskScheduler[3] 顯示線程池任務(wù)調(diào)度器是這樣調(diào)度任務(wù)的:

  1. /// <summary> 
  2. /// Schedules a task to the ThreadPool. 
  3. /// </summary> 
  4. /// <param name="task">The task to schedule.</param> 
  5. protected internal override void QueueTask(Task task) 
  6.      TaskCreationOptions options = task.Options; 
  7.      if ((options & TaskCreationOptions.LongRunning) != 0) 
  8.      { 
  9.           // Run LongRunning tasks on their own dedicated thread. 
  10.           Thread thread = new Thread(s_longRunningThreadWork); 
  11.           thread.IsBackground = true; // Keep this thread from blocking process shutdown 
  12.           thread.Start(task); 
  13.     } 
  14.     else 
  15.     { 
  16.          // Normal handling for non-LongRunning tasks. 
  17.         bool preferLocal = ((options & TaskCreationOptions.PreferFairness) == 0); 
  18.         ThreadPool.UnsafeQueueUserWorkItemInternal(task, preferLocal); 
  19.     } 

請(qǐng)注意8-14行:若上層使用者將LongRunning任務(wù)應(yīng)用到默認(rèn)的任務(wù)調(diào)度器(也即ThreadPoolTaskScheduler),ThreadPoolTaskScheduler會(huì)有一個(gè)兜底方案:會(huì)將任務(wù)放在獨(dú)立線程上執(zhí)行。

何時(shí)不使用線程池線程

有幾種應(yīng)用場景,其中適合創(chuàng)建并管理自己的線程,而非使用線程池線程:

  • 需要一個(gè)前臺(tái)線程。
  • 需要具有特定優(yōu)先級(jí)的線程。
  • 擁有會(huì)導(dǎo)致線程長時(shí)間阻塞的任務(wù)。線程池具有最大線程數(shù),因此大量被阻塞的線程池線程可能會(huì)阻止任務(wù)啟動(dòng)。
  • 需將線程放入單線程單元。所有 ThreadPool 線程均位于多線程單元中。
  • 需具有與線程關(guān)聯(lián)的穩(wěn)定標(biāo)識(shí),或需將一個(gè)線程專用于一項(xiàng)任務(wù)。

Q3. 既然要自定義任務(wù)調(diào)度器,那我們就來倒騰?

實(shí)現(xiàn)TaskScheduler 抽象類,其中的抓手是“調(diào)度”,也就是 QueueTask、TryExecuteTask 方法,之后你可以自定義數(shù)據(jù)結(jié)構(gòu)和算法, 從數(shù)據(jù)結(jié)構(gòu)中調(diào)度出任務(wù)執(zhí)行。

給個(gè)例子:

  1. public sealed class CustomTaskScheduler : TaskScheduler, IDisposable 
  2.     { 
  3.         private BlockingCollection<Task> tasksCollection = new BlockingCollection<Task>(); 
  4.         private readonly Thread mainThread = null
  5.         public CustomTaskScheduler() 
  6.         { 
  7.             mainThread = new Thread(new ThreadStart(Execute)); 
  8.             if (!mainThread.IsAlive) 
  9.             { 
  10.                 mainThread.Start(); 
  11.             } 
  12.         } 
  13.         private void Execute() 
  14.         { 
  15.             foreach (var task in tasksCollection.GetConsumingEnumerable()) 
  16.             { 
  17.                 TryExecuteTask(task); 
  18.             } 
  19.         } 
  20.         protected override IEnumerable<Task> GetScheduledTasks() 
  21.         { 
  22.             return tasksCollection.ToArray(); 
  23.         } 
  24.         protected override void QueueTask(Task task) 
  25.         { 
  26.             if (task != null
  27.                 tasksCollection.Add(task);            
  28.         } 
  29.         protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
  30.         { 
  31.             return false
  32.         } 
  33.         private void Dispose(bool disposing) 
  34.         { 
  35.             if (!disposing) return
  36.             tasksCollection.CompleteAdding(); 
  37.             tasksCollection.Dispose(); 
  38.         } 
  39.         public void Dispose() 
  40.         { 
  41.             Dispose(true); 
  42.             GC.SuppressFinalize(this); 
  43.         } 
  44.     } 

引用鏈接

[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

 

責(zé)任編輯:武曉燕 來源: 全棧碼農(nóng)畫像
相關(guān)推薦

2021-10-26 14:40:03

MySQL SQL 語句數(shù)據(jù)庫

2021-11-04 14:32:17

Spring 面試作用域

2021-10-21 14:43:23

Java 語言 Java 基礎(chǔ)

2021-07-26 14:59:23

面試Redis內(nèi)存數(shù)據(jù)庫

2021-09-07 14:46:42

面試網(wǎng)絡(luò)HTTP 協(xié)議

2024-02-23 19:17:12

構(gòu)造函數(shù)C++開發(fā)

2023-11-28 18:09:49

Java多態(tài)

2022-09-03 11:36:11

Python文件網(wǎng)絡(luò)

2021-10-26 17:05:55

Redis字符串復(fù)雜度

2021-08-01 22:59:43

Object八股文quals

2021-04-14 10:02:59

網(wǎng)絡(luò)八股文協(xié)議

2023-11-29 17:28:07

2021-05-20 11:43:57

操作系統(tǒng)硬件軟件

2021-08-12 09:28:24

Java多線程變量

2024-10-12 09:26:32

線程池系統(tǒng)核心線程

2023-12-12 13:38:00

Java異步編程

2023-01-13 18:04:03

面試題消息中間件

2021-07-05 07:55:11

String[]byte轉(zhuǎn)換

2024-06-05 10:59:51

2022-05-27 14:43:45

JVM字節(jié)碼指令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)