網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、使用線程的理由
1、可以使用線程將代碼同其他代碼隔離,提高應(yīng)用程序的可靠性。
2、可以使用線程來(lái)簡(jiǎn)化編碼。
3、可以使用線程來(lái)實(shí)現(xiàn)并發(fā)執(zhí)行。
二、基本知識(shí)
1、進(jìn)程與線程:進(jìn)程作為操作系統(tǒng)執(zhí)行程序的基本單位,擁有應(yīng)用程序的資源,進(jìn)程包含線程,進(jìn)程的資源被線程共享,線程不擁有資源。
2、前臺(tái)線程和后臺(tái)線程:通過(guò)Thread類新建線程默認(rèn)為前臺(tái)線程。當(dāng)所有前臺(tái)線程關(guān)閉時(shí),所有的后臺(tái)線程也會(huì)被直接終止,不會(huì)拋出異常。
3、掛起(Suspend)和喚醒(Resume):由于線程的執(zhí)行順序和程序的執(zhí)行情況不可預(yù)知,所以使用掛起和喚醒容易發(fā)生死鎖的情況,在實(shí)際應(yīng)用中應(yīng)該盡量少用。
4、阻塞線程:Join,阻塞調(diào)用線程,直到該線程終止。
5、終止線程:Abort:拋出 ThreadAbortException 異常讓線程終止,終止后的線程不可喚醒。Interrupt:拋出 ThreadInterruptException 異常讓線程終止,通過(guò)捕獲異常可以繼續(xù)執(zhí)行。
6、線程優(yōu)先級(jí):Highest AboveNormal Normal BelowNormal Lowest ,默認(rèn)為Normal。
三、線程的使用
線程函數(shù)通過(guò)委托傳遞,可以不帶參數(shù),也可以帶參數(shù)(只能有一個(gè)參數(shù)),可以用一個(gè)類或結(jié)構(gòu)體封裝參數(shù)。
案例:
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(TestMethod));//創(chuàng)建無(wú)參數(shù)數(shù)線程
Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));//創(chuàng)建帶參數(shù)的線程
//設(shè)置為后臺(tái)進(jìn)程
t1.IsBackground = true;
t2.IsBackground = true;
t1.Start();
t2.Start("hello");
Console.ReadKey();
}
public static void TestMethod()
{
Console.WriteLine("不帶參數(shù)的線程函數(shù)");
}
//參數(shù)要定義為object 類型
public static void TestMethod(object data)
{
string datastr = data as string;
Console.WriteLine("帶參數(shù)的線程函數(shù),參數(shù)為:{0}", datastr);
}
}
四、線程池
由于線程的創(chuàng)建和銷毀需要耗費(fèi)一定的開(kāi)銷,過(guò)多的使用線程會(huì)造成內(nèi)存資源的浪費(fèi),出于對(duì)性能的考慮,于是引入了線程池的概念。線程池維護(hù)一個(gè)請(qǐng)求隊(duì)列,線程池的代碼從隊(duì)列提取任務(wù),然后委派給線程池的一個(gè)線程執(zhí)行,線程執(zhí)行完不會(huì)被立即銷毀,這樣既可以在后臺(tái)執(zhí)行任務(wù),又可以減少線程創(chuàng)建和銷毀所帶來(lái)的開(kāi)銷。
線程池線程默認(rèn)為后臺(tái)線程(IsBackground)。
class Program
{
static void Main(string[] args)
{
//將工作項(xiàng)加入到線程池隊(duì)列中,這里可以傳遞一個(gè)線程參數(shù)
ThreadPool.QueueUserWorkItem(TestMethod, "Hello");
Console.ReadKey();
}
//線程函數(shù)
public static void TestMethod(object data)
{
string datastr = data as string;
Console.WriteLine(datastr);
}
}
五、Task類
使用ThreadPool的QueueUserWorkItem()方法發(fā)起一次異步的線程執(zhí)行很簡(jiǎn)單,但是該方法最大的問(wèn)題是沒(méi)有一個(gè)內(nèi)建的機(jī)制讓你知道操作什么時(shí)候完成,有沒(méi)有一個(gè)內(nèi)建的機(jī)制在操作完成后獲得一個(gè)返回值。為此,可以使用System.Threading.Tasks中的Task類。
構(gòu)造一個(gè)Task<TResult>對(duì)象,并為泛型TResult參數(shù)傳遞一個(gè)操作的返回類型。
class Program
{
static void Main(string[] args)
{
Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
t.Start();
t.Wait();
Console.WriteLine(t.Result);
Console.ReadKey();
}
private static Int32 Sum(Int32 n)
{
Int32 sum = 0;
for (; n > 0; --n)
checked{ sum += n;} //結(jié)果太大,拋出異常
return sum;
}
}
一個(gè)任務(wù)完成時(shí),自動(dòng)啟動(dòng)一個(gè)新任務(wù)。
一個(gè)任務(wù)完成后,它可以啟動(dòng)另一個(gè)任務(wù),下面重寫了前面的代碼,不阻塞任何線程。
class Program
{
static void Main(string[] args)
{
Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
t.Start();
//t.Wait();
Task cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}", t.Result));
Console.ReadKey();
}
private static Int32 Sum(Int32 n)
{
Int32 sum = 0;
for (; n > 0; --n)
checked { sum += n; } //結(jié)果溢出,拋出異常
return sum;
}
}
六、委托異步執(zhí)行
委托的異步調(diào)用:BeginInvoke() 和 EndInvoke()
namespace Test
{
public delegate string MyDelegate(object data);
class Program
{
static void Main(string[] args)
{
MyDelegate mydelegate = new MyDelegate(TestMethod);
IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param");
//異步執(zhí)行完成
string resultstr = mydelegate.EndInvoke(result);
}
//線程函數(shù)
public static string TestMethod(object data)
{
string datastr = data as string;
Console.WriteLine(datastr);
return datastr;
}
//異步回調(diào)函數(shù)
public static void TestCallback(IAsyncResult data)
{
Console.WriteLine(data.AsyncState);
}
}
}
異步回調(diào)函數(shù)在上面線程函數(shù)執(zhí)行結(jié)束后,將要退出時(shí)執(zhí)行。
原文鏈接:https://www.cnblogs.com/wml-it/p/14808683.html
相關(guān)推薦
- 2022-04-11 C#實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能(1)(窗體應(yīng)用)_C#教程
- 2022-06-22 git版本庫(kù)介紹及本地創(chuàng)建的三種場(chǎng)景方式_其它綜合
- 2022-04-23 R語(yǔ)言繪制line?plot線圖示例詳解_R語(yǔ)言
- 2022-09-10 pycharm下載包的時(shí)候出現(xiàn)?no?information?available的解決_python
- 2022-02-25 C++構(gòu)造函數(shù)的初始化列表詳解_C 語(yǔ)言
- 2022-10-20 docker中的volume和bind?mount區(qū)別講解_docker
- 2022-06-14 Flutter網(wǎng)絡(luò)請(qǐng)求Dio庫(kù)的使用及封裝詳解_Android
- 2021-12-12 Docker?Consul概述以及集群環(huán)境搭建步驟(圖文詳解)_docker
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支