網站首頁 編程語言 正文
1.什么是thread
當我們提及多線程的時候會想到thread和threadpool,這都是異步操作,threadpool其實就是thread的集合,具有很多優勢,不過在任務多的時候全局隊列會存在競爭而消耗資源。thread默認為前臺線程,主程序必須等線程跑完才會關閉,而threadpool相反。
總結:threadpool確實比thread性能優,但是兩者都沒有很好的api區控制,如果線程執行無響應就只能等待結束,從而誕生了task任務。
2.什么是task
?task簡單地看就是任務,那和thread有什么區別呢?Task的背后的實現也是使用了線程池線程,但它的性能優于ThreadPoll,因為它使用的不是線程池的全局隊列,而是使用的本地隊列,使線程之間的資源競爭減少。同時Task提供了豐富的API來管理線程、控制。但是相對前面的兩種耗內存,Task依賴于CPU對于多核的CPU性能遠超前兩者,單核的CPU三者的性能沒什么差別。
3.創建一個task任務有兩種模式:
1.使用factory創建會直接執行,使用new創建不會執行,必須等到start啟動之后才執行。
? public void test() { var testTask = new Task(() => { Console.WriteLine("task start"); }); testTask.Start(); var factoryTeak = Task.Factory.StartNew(() => { Console.WriteLine("factory task start"); }); } ?
2.我們來看看task的生命周期
?var testTask = new Task(() => { Console.WriteLine("task start"); System.Threading.Thread.Sleep(2000); }); Console.WriteLine(testTask.Status); testTask.Start(); Console.WriteLine(testTask.Status); Console.WriteLine(testTask.Status); testTask.Wait(); Console.WriteLine(testTask.Status); Console.WriteLine(testTask.Status); ?
輸出結果:
Created
task start
Running
Running
RanToCompletion
RanToCompletion
可以看出task確實是異步執行,并且wait很好地控制了task。
3.下面演示幾個控制task的方法
var testTask = new Task(() => { Console.WriteLine("task start"); System.Threading.Thread.Sleep(2000); }); testTask.Start(); testTask.Wait();
var testTask = new Task(() => { Console.WriteLine("task start"); System.Threading.Thread.Sleep(2000); }); testTask.Start(); var factoryTeak = Task.Factory.StartNew(() => { Console.WriteLine("factory task start"); }); Task.WaitAll(testTask, factoryTeak); Console.WriteLine("end"); ?
var testTask = new Task(() => { Console.WriteLine("task start"); System.Threading.Thread.Sleep(2000); }); testTask.Start(); var factoryTeak = Task.Factory.StartNew(() => { Console.WriteLine("factory task start"); }); Task.WaitAny(testTask, factoryTeak); Console.WriteLine("end");
通過wait()對單個task進行等待,Task.waitall()對多個task進行等待,waitany()執行任意一個task就往下繼續執行。
4.task的回調執行
var testTask = new Task(() => { Console.WriteLine("task start"); System.Threading.Thread.Sleep(2000); }); testTask.Start(); var resultTest = testTask.ContinueWith<string>((Task) => { Console.WriteLine("testTask end"); return "end"; }); Console.WriteLine(resultTest.Result);
5.task的取消
首先創建一個取消task的令牌的實例,在不啟動task直接取消:
var tokenSource = new CancellationTokenSource();//創建取消task實例 var testTask = new Task(() => { for (int i = 0; i < 6; i++) { System.Threading.Thread.Sleep(1000); } },tokenSource.Token); Console.WriteLine(testTask.Status); tokenSource.Token.Register(()=> { Console.WriteLine("task is to cancel"); }); tokenSource.Cancel(); Console.WriteLine(testTask.Status);
?輸出結果:
Created
task is to cancel
Canceled
如果task啟動了真的取消了task?
var tokenSource = new CancellationTokenSource();//創建取消task實例 var testTask = new Task(() => { for (int i = 0; i <6; i++) { System.Threading.Thread.Sleep(1000); } },tokenSource.Token); Console.WriteLine(testTask.Status); testTask.Start(); Console.WriteLine(testTask.Status); tokenSource.Token.Register(()=> { Console.WriteLine("task is to cancel"); }); tokenSource.Cancel(); Console.WriteLine(testTask.Status); for (int i = 0; i < 10; i++) { System.Threading.Thread.Sleep(1000); Console.WriteLine(testTask.Status); }
輸出結果:
Created
WaitingToRun
task is to cancel
Running
Running
Running
Running
Running
Running
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion
?可以看出其實并沒有取消task,此時task還在繼續跑。
6.task的嵌套
var parentTask = new Task(()=> { var childTask = new Task(() =>{ System.Threading.Thread.Sleep(2000); Console.WriteLine("childTask to start"); }); childTask.Start(); Console.WriteLine("parentTask to start"); }); parentTask.Start(); parentTask.Wait(); Console.WriteLine("end");
此時為普通關聯,父task和子task沒影響
var parentTask = new Task(()=> { var childTask = new Task(() =>{ System.Threading.Thread.Sleep(2000); Console.WriteLine("childTask to start"); }, TaskCreationOptions.AttachedToParent); childTask.Start(); Console.WriteLine("parentTask to start"); } ); parentTask.Start(); parentTask.Wait(); Console.WriteLine("end");
此時為父task和子task關聯,wait會一直等待父子task執行完。
6.task死鎖的問題
我們可以設置最大等待時間,如果超過了等待時間,就不再等待,下面我們來修改代碼,設置最大等待時間為5秒(項目中可以根據實際情況設置),如果超過5秒就輸出哪個任務出錯了
7.對Spinlock的使用
舉例來說Parallel.for和Parallel.foreach是線程不安全的,有可能達不到你的預期,此時就需要加鎖來解決此問題,我們可以加lock和spinlock(自旋鎖)來解決
SpinLock slock = new SpinLock(false); var testLock= new object(); long sum1 = 0; long sum2 = 0; long sum3 = 0; Parallel.For(0, 100000, i => { sum1 += i; }); Parallel.For(0, 100000, i => { bool lockTaken = false; try { slock.Enter(ref lockTaken); sum2 += i; } finally { if (lockTaken) slock.Exit(false); } }); Parallel.For(0, 100000, i => { lock(testLock) { sum3 += i; }; }); Console.WriteLine("Num1的值為:{0}", sum1); Console.WriteLine("Num2的值為:{0}", sum2); Console.WriteLine("Num3的值為:{0}", sum3);
輸出結果:
Num1的值為:1660913202
Num2的值為:4999950000
Num3的值為:4999950000
Num1的值為:2754493646
Num2的值為:4999950000
Num3的值為:4999950000
Num1的值為:4999950000
Num2的值為:4999950000
Num3的值為:4999950000
最后看看threadpoll和task的結構圖:
threadpool:
?task:
原文鏈接:https://blog.csdn.net/qq_40677590/article/details/102797838
相關推薦
- 2022-06-01 詳解C語言的void*空指針_C 語言
- 2022-05-10 MAC m1使用homebrew安裝redis報錯
- 2022-05-04 C#設計模式之策略模式_C#教程
- 2023-01-03 flutter中的布局和響應式app方法示例_Android
- 2022-06-20 k8s在go語言中的使用及client?初始化簡介_Golang
- 2023-04-12 Docker?login和logout的使用_docker
- 2023-10-15 webrtc 測試video_loopback
- 2022-11-05 React+CSS?實現繪制橫向柱狀圖_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支