Perl線程的生命周期
本文和大家重點(diǎn)討論一下Perl線程的生命周期,主要包括創(chuàng)建Perl線程,join方法和detach方法兩大部分內(nèi)容,希望通過(guò)本文的介紹你對(duì)Perl線程的生命周期有一定的認(rèn)識(shí)。
Perl線程的生命周期
創(chuàng)建Perl線程
Perl線程作為Perl中的一種實(shí)體,其一生可以粗略的分為創(chuàng)建,運(yùn)行與退出這三個(gè)階段。創(chuàng)建使得Perl線程從無(wú)到有,運(yùn)行則是Perl線程完成其主要工作的階段,退出自然就是指Perl線程的消亡。Perl線程的運(yùn)行和普通函數(shù)的執(zhí)行非常類似,有其入口參數(shù),一段特定的代碼流程以及執(zhí)行完畢后返回的一個(gè)或一組結(jié)果,唯一與普通函數(shù)調(diào)用的不同之處就在于新建Perl線程的執(zhí)行與當(dāng)前Perl線程的執(zhí)行是并行的。
Perl里創(chuàng)建一個(gè)新的Perl線程非常簡(jiǎn)單,主要有兩種方法,他們分別是:
使用threads包的create()方法,例如
清單3.通過(guò)create()方法創(chuàng)建Perl線程
- usethreads;
- subsay_hello
- {
- printf("Hellothread!@_.\n");
- return(rand(10));
- }
- my$t1=threads->create(\&say_hello,"param1","param2");
- my$t2=threads->create("say_hello","param3","param4");
- my$t3=threads->create(
- sub{
- printf("Hellothread!@_\n");
- return(rand(10));
- },
- "param5",
- "param6");
使用async{}塊創(chuàng)建Perl線程,例如
清單4.通過(guò)async{}塊創(chuàng)建Perl線程
- #!/usr/bin/perl
- #
- usethreads;
- my$t4=async{
- printf("Hellothread!\n");
- };
#p#
join方法和detach方法
Perl線程一旦被成功創(chuàng)建,它就立刻開(kāi)始運(yùn)行了,這個(gè)時(shí)候你面臨兩種選擇,分別是join或者detach這個(gè)新建Perl線程。當(dāng)然你也可以什么都不做,不過(guò)這可不是一個(gè)好習(xí)慣,后面我們會(huì)解釋這是為什么。
我們先來(lái)看看join方法,這也許是大多數(shù)情況下你想要的。從字面上來(lái)理解,join就是把新創(chuàng)建的Perl線程結(jié)合到當(dāng)前的主Perl線程中來(lái),把它當(dāng)成是主Perl線程的一部分,使他們合二為一。join會(huì)觸發(fā)兩個(gè)動(dòng)作,首先,主Perl線程會(huì)索取新建Perl線程執(zhí)行結(jié)束以后的返回值;其次,新建Perl線程在執(zhí)行完畢并返回結(jié)果以后會(huì)自動(dòng)釋放它自己所占用的系統(tǒng)資源。例如
清單5.使用join()方法收割新建Perl線程
- #!/usr/bin/perl
- #
- usethreads;
- subfunc{
- sleep(1);
- return(rand(10));
- }
- my$t1=threads->create(\&func);
- my$t2=threads->create(\&func);
- printf("dosomethinginthemainthread\n");
- my$t1_res=$t1->join();
- my$t2_res=$t2->join();
- printf("t1_res=$t1_res\nt2_res=$t2_res\n");
由此我們不難發(fā)現(xiàn),調(diào)用join的時(shí)機(jī)是一個(gè)十分有趣的問(wèn)題。如果調(diào)用join方法太早,新建Perl線程尚未執(zhí)行完畢,自然就無(wú)法返回任何結(jié)果,那么這個(gè)時(shí)候,主Perl線程就不得不被阻塞,直到新建Perl線程執(zhí)行完畢之后,才能獲得返回值,然后資源會(huì)被釋放,join才能結(jié)束,這在很大程度上破話了Perl線程之間的并行性。相反,如果調(diào)用join方法太晚,新建Perl線程早已執(zhí)行完畢,由于一直沒(méi)有機(jī)會(huì)返回結(jié)果,它所占用的資源就一直無(wú)法得到釋放,直到被join為止,這在很大程度上浪費(fèi)了寶貴的系統(tǒng)資源。因此,join新建Perl線程的最好時(shí)機(jī)應(yīng)該是在它剛剛執(zhí)行完畢的時(shí)候,這樣既不會(huì)阻塞當(dāng)前Perl線程的執(zhí)行,又可以及時(shí)釋放新建Perl線程所占用的系統(tǒng)資源。
我們?cè)賮?lái)看看detach方法,這也許是最省心省力的處理方法了。從字面上來(lái)理解,detach就是把新創(chuàng)建的Perl線程與當(dāng)前的主Perl線程剝離開(kāi)來(lái),讓它從此和主Perl線程無(wú)關(guān)。當(dāng)你使用detach方法的時(shí)候,表明主Perl線程并不關(guān)心新建Perl線程執(zhí)行以后返回的結(jié)果,新建Perl線程執(zhí)行完畢后Perl會(huì)自動(dòng)釋放它所占用的資源。
一個(gè)新建Perl線程一旦被detach以后,就無(wú)法再join了。當(dāng)你使用detach方法剝離Perl線程的時(shí)候,有一點(diǎn)需要特別注意,那就是你需要保證被創(chuàng)建的Perl線程先于主Perl線程結(jié)束,否則你創(chuàng)建的Perl線程會(huì)被迫結(jié)束,除非這種結(jié)果正是你想要的,否則這也許會(huì)造成異常情況的出現(xiàn),并增加程序調(diào)試的難度。
本節(jié)的開(kāi)始我們提到,新Perl線程被創(chuàng)建以后,如果既不join,也不detach不是一個(gè)好習(xí)慣,這是因?yàn)槌敲鞔_地調(diào)用detach方法剝離Perl線程,Perl會(huì)認(rèn)為你也許要在將來(lái)的某一個(gè)時(shí)間點(diǎn)調(diào)用join,所以新建Perl線程的返回值會(huì)一直被保存在內(nèi)存中以備不時(shí)之需,它所占用的系統(tǒng)資源也一直不會(huì)得到釋放。然而實(shí)際上,你打算什么也不做,因此寶貴的系統(tǒng)資源直到整個(gè)Perl應(yīng)用結(jié)束時(shí)才被釋放。同時(shí),由于你即沒(méi)有調(diào)用join有沒(méi)有調(diào)用detach,應(yīng)用結(jié)束時(shí)Perl還會(huì)返回給你一個(gè)Perl線程非正常結(jié)束的警告。
Perl線程的消亡
大多數(shù)情況下,你希望你創(chuàng)建的Perl線程正常退出,這就意味著Perl線程所對(duì)應(yīng)的函數(shù)體在執(zhí)行完畢后返回并釋放資源。例如在清單5的示例中,新建Perl線程被join以后的退出過(guò)程??墒?,如果由于detach不當(dāng)或者由于主線因某些意外的異常提前結(jié)束了,盡管它所創(chuàng)建的Perl線程可能尚未執(zhí)行完畢,但是他們還是會(huì)被強(qiáng)制中止,正所謂皮之不存,毛將焉附。這時(shí)你也許會(huì)得到一個(gè)類似于“Perlexitedwithactivethreads”的警告。
當(dāng)然,你也可以顯示地調(diào)用exit()方法來(lái)結(jié)束一個(gè)Perl線程,不過(guò)值得注意的是,默認(rèn)情況下,如果你在一個(gè)Perl線程中調(diào)用了exit()方法,其他Perl線程都會(huì)隨之一起結(jié)束,在很多情況下,這也許不是你想要的,如果你希望exit()方法只在調(diào)用它的Perl線程內(nèi)生效,那么你在創(chuàng)建該P(yáng)erl線程的時(shí)候就需要設(shè)置’exit’=>’thread_only’。例如
清單7.為某個(gè)Perl線程設(shè)置’exit’=>’thread_only’屬性
- #!/usr/bin/perl
- #
- usethreads;
- subsay_hello{
- printf("Hellothread!@_.\n");
- sleep(10);
- printf("Bye\n");
- }
- subquick_exit{
- printf("Iwillbeexitinnotime\n");
- exit(1);
- }
- my$t1=threads->create(\&say_hello,"param1","param2");
- my$t2=threads->create({'exit'=>'thread_only'},\&quick_exit);
- $t1->join();
- $t2->join();
如果你希望每個(gè)Perl線程的exit方法都只對(duì)自己有效,那么在每次創(chuàng)建一個(gè)新Perl線程的時(shí)候都去要顯式設(shè)置’exit’=>’thread_only’屬性顯然有些麻煩,你也可以在引入threads包的時(shí)候設(shè)置這個(gè)屬性在全局范圍內(nèi)有效。
【編輯推薦】