系列文章目錄
??座右銘??:人的一生這么長(zhǎng)、你憑什么用短短的幾年去衡量自己的一生!
??個(gè)人主頁(yè):清靈白羽 漾情天殤_計(jì)算機(jī)底層原理,深度解析C++,自頂向下看Java-CSDN博客
??相關(guān)文章??:清靈白羽 漾情天殤-CSDN博客
目錄
系列文章目錄
前言
一、Thread構(gòu)造方法
? ? ? ? 1、Thread():
? ? ? ? 2、Thread(Runnable target):
? ? ? ? 拓展:
? ? ? ? 1、Thread.sleep():
? ? ? ? 2、sleep為什么要捕獲異常:
? ? ? ? 3、捕獲異常之后呢?
? ? ? ? 1、提供線程中斷的機(jī)制
? ? ? ? 2、保留中斷狀態(tài)
? ? ? ? 3、提供了可靠的中斷相應(yīng)機(jī)制
? ? ? ? 4、線程收到異常之后會(huì)做什么呢?
? ? ? ? 1、恢復(fù)中斷狀態(tài)、????????
? ? ? ? 2、根據(jù)實(shí)際需求進(jìn)行是當(dāng)?shù)那謇砉ぷ?/p>
? ? ? ? 補(bǔ)充
? ? ? ? 3、Thread(Runnable target, String name)
二、其它方法
前言
? ? ? ? 這篇文章我來(lái)為大家詳細(xì)地介紹一下Thread類的常見(jiàn)的方法,以及線程的一些相關(guān)操作,當(dāng)中包括如何中止線程、等待線程。
一、Thread構(gòu)造方法
? ? ? ? 在Java當(dāng)中Thread類是用于創(chuàng)建和操作線程的主要類之一,Thread類的常見(jiàn)構(gòu)造方法如下:
? ? ? ? 1、Thread():
? ? ? ? 這是Thread類的默認(rèn)構(gòu)造方法,他創(chuàng)建一個(gè)新的線程對(duì)象,但是如果我們不指定線程的執(zhí)行任務(wù),它將不會(huì)進(jìn)行任何操作。
public class Main { public static void main(String[] args) { Thread thread = new Thread(); thread.start(); } }
? ? ? ? 2、Thread(Runnable target):
? ? ? ? 這個(gè)構(gòu)造方法接受一個(gè)實(shí)現(xiàn)了Runnable接口的對(duì)象作為參數(shù),通過(guò)這樣的方法我們可以在新線程當(dāng)中執(zhí)行實(shí)現(xiàn)了Runnable接口的對(duì)象的run()方法。
? ? ? ? Thread類是Java當(dāng)中用于創(chuàng)建和管理線程的類,每個(gè)線程都是通過(guò)Thread類的實(shí)例表示的,Runnable接口是一個(gè)功能性接口,它只包含了一個(gè)抽象方法run(),當(dāng)一個(gè)類實(shí)現(xiàn)了Runnable接口并且提供了run()方法的具體實(shí)現(xiàn)的時(shí)候,該類的實(shí)例就可以被傳遞給Thread類的構(gòu)造方法,這個(gè)實(shí)現(xiàn)了Runnable接口的類通常包含了需要在新線程當(dāng)中執(zhí)行的代碼。
? ? ? ? 這個(gè)構(gòu)造方法接受一個(gè)實(shí)現(xiàn)了Runnable接口的對(duì)象作為參數(shù),當(dāng)創(chuàng)建一個(gè)新的Thread實(shí)例的時(shí)候,可以通過(guò)這個(gè)構(gòu)造方法指定該線程要執(zhí)行的代碼,而這段代碼通常就是傳遞進(jìn)來(lái)的RUnnable對(duì)象的run()方法。
? ? ? ? 為什么要采用這樣的方式呢,因?yàn)槲覀兛梢詫⒉煌娜蝿?wù)封裝在實(shí)現(xiàn)了Runnable接口的類的實(shí)例當(dāng)中,并且將這些任務(wù)交給Thread對(duì)象執(zhí)行,從而實(shí)現(xiàn)多線程編程,這種方式比直接拓展Thread類更加靈活,因?yàn)橐粋€(gè)類只能直接繼承一個(gè)父類,但是可以實(shí)現(xiàn)多個(gè)接口,因此使用Runnable接口可以更好地支持代碼的復(fù)用和組合。下面我為大家用代碼來(lái)進(jìn)行演示:
class MyTask implements Runnable{ @Override public void run() { for (int i = 0;i < 5; i++){ System.out.println("Thread running"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Main { public static void main(String[] args) { MyTask myTask = new MyTask(); Thread thread = new Thread(myTask); thread.start(); for (int i = 0;i < 5;i++){ System.out.println("主線程正在執(zhí)行"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
? ? ? ? 拓展:
? ? ? ? 1、Thread.sleep():
? ? ? ? 這個(gè)方法會(huì)讓當(dāng)前線程休眠指定的時(shí)間,所謂的當(dāng)前線程是指調(diào)用這個(gè)sleep方法的線程,例如如果我們?cè)趍ain方法也就是主線程當(dāng)中調(diào)用這個(gè)方法就是讓主線程進(jìn)入休眠,如果我們?cè)谧约憾x的實(shí)現(xiàn)了Runnable接口的類當(dāng)中調(diào)用了這個(gè)方法就是新的線程在休眠。
? ? ? ? 2、sleep為什么要捕獲異常:
? ? ? ? 不僅僅是sleep()方法,Thread類當(dāng)中幾乎所有的方法都需要捕獲異常,或者拋出異常來(lái)處理這個(gè)問(wèn)題,包括我們后需要講到的join(),wait()方法都需要這樣做,那么這是為什么呢?這是因?yàn)樵贘ava當(dāng)中線程在休眠的時(shí)候是看可以被打斷的,那么這個(gè)時(shí)候sleep就會(huì)發(fā)出'InterruptedException'異常來(lái)提醒線程已經(jīng)被中斷,因此在使用Thread.sleep()方法的時(shí)候需要處理這個(gè)異常,通常的做法是使用try-catch塊進(jìn)行環(huán)繞并進(jìn)行相應(yīng)的處理,比如恢復(fù)中斷狀態(tài)或者執(zhí)行其它邏輯,在我為大家寫的示例代碼當(dāng)中即使我們沒(méi)有明確的中斷線程的代碼,但是為了保持良好的編碼習(xí)慣,我們依然捕獲了'InterruptedException'異常,這樣做的好處是即使未來(lái)我們對(duì)線程進(jìn)行了中斷操作,代碼也已經(jīng)準(zhǔn)備好了處理這種情況,提高了代碼的健壯性和可維護(hù)性,有很多小伙伴在初學(xué)的時(shí)候不明白為什么這里一定要進(jìn)行異常處理,希望我的觀點(diǎn)可以幫助到大家。
? ? ? ? 3、捕獲異常之后呢?
? ? ? ? Thread這個(gè)類在設(shè)計(jì)的時(shí)候讓Thread.sleep()拋出'InterruptedException'異常的主要目的是為了提供一種機(jī)制來(lái)響應(yīng)線程的中斷請(qǐng)求,Java中的線程中斷機(jī)制允許一個(gè)線程中斷另外一個(gè)線程的執(zhí)行,當(dāng)一個(gè)線程調(diào)用另一個(gè)線程的'interrupted'方法的時(shí)候,目標(biāo)線程也就是被中斷的線程就會(huì)收到一個(gè)中斷請(qǐng)求,如果這個(gè)時(shí)候目標(biāo)線程正在進(jìn)行sleep(),wait(),join()方法當(dāng)中休眠那么這個(gè)時(shí)候中斷機(jī)制會(huì)將這個(gè)線程強(qiáng)制喚醒,并且喚醒之后收到一個(gè)'InterruptedException'異常信息。
? ? ? ? 1、提供線程中斷的機(jī)制
? ? ? ? 通過(guò)拋出異常,允許線程在休眠期間被中斷,使得線程可以在收到中斷請(qǐng)求以后做出相應(yīng)的處理,例如終止執(zhí)行,清理資源等。
? ? ? ? 2、保留中斷狀態(tài)
? ? ? ? 當(dāng)'InterruptedException'異常被捕獲之后通常的做法是在catch塊當(dāng)中處理異常并且恢復(fù)線程中的中斷狀態(tài),以便其它部分的代碼可以檢查到線程被中斷,并且采取相應(yīng)的行動(dòng)。
? ? ? ? 3、提供了可靠的中斷相應(yīng)機(jī)制
? ? ? ? 通過(guò)拋出異常,確保了即使線程處于休眠狀態(tài),也能夠及時(shí)響應(yīng)中斷請(qǐng)求(因?yàn)樗鼤?huì)被立刻喚醒,這一點(diǎn)上面我們已經(jīng)講過(guò)了,這里就不再重復(fù)了),而不會(huì)無(wú)限地等待,這樣可以使得多線程程序更加可靠和健壯。
? ? ? ? 4、線程收到異常之后會(huì)做什么呢?
? ? ? ? 1、恢復(fù)中斷狀態(tài)、????????
? ? ? ? 在catch塊中使用‘Thread.currentThread().interrupt()’(這行代碼我剛才的實(shí)例里面沒(méi)有講到,后面會(huì)為大家講到。所以這里大家只做了解)來(lái)重新設(shè)置中斷狀態(tài),以便其它部分的代碼能夠檢查到線程是否被中斷。
? ? ? ? 2、根據(jù)實(shí)際需求進(jìn)行是當(dāng)?shù)那謇砉ぷ?/h5>
? ? ? ? 例如釋放資源管理連接等,然后再根據(jù)業(yè)務(wù)的邏輯決定這個(gè)線程是否要繼續(xù)執(zhí)行,或者直接終止線程的執(zhí)行不再被調(diào)用。
? ? ? ? 補(bǔ)充
? ? ? ? 我相信有很多小伙伴不太明白關(guān)于我上面講到的關(guān)于恢復(fù)線程中斷狀態(tài)的概念,我在這里特別補(bǔ)充一下,線程中斷狀態(tài)是一個(gè)標(biāo)志位,是線程TCB(線程控制塊)內(nèi)部自己維護(hù)的一個(gè)標(biāo)志位用于表示線程是否被中斷,當(dāng)目標(biāo)線程被中斷的時(shí)候,中斷狀態(tài)就會(huì)被設(shè)置為true(初始狀態(tài)為false),當(dāng)線程在阻塞狀態(tài)下(比如調(diào)用sleep、join等方法的時(shí)候)被中斷的時(shí)候,會(huì)拋出'InterruptedException'異常,并且在拋出異常之前Java會(huì)清楚線程的中斷狀態(tài),將中斷狀態(tài)重新設(shè)置為false,
? ? ? ? 因此在處理這個(gè)異常的時(shí)候,通常需要更新設(shè)置線程的中斷狀態(tài),以便將中斷信息傳遞給更高層的調(diào)用棧,catch塊當(dāng)中的Thread.currentThread().interrupt()’會(huì)將線程的中斷狀態(tài)設(shè)置為之前的值,如果之前是true那么就設(shè)置為true如果之前是false亦然,在拋出異常之前清楚中斷狀態(tài)時(shí)為了讓線程在異常處理之后繼續(xù)執(zhí)行,不會(huì)誤認(rèn)為被中斷過(guò),如果不清理中斷狀態(tài),即使線程處理了’InterruptedException‘這個(gè)異常,但是在異常處理之后線程的中斷狀態(tài)仍然為true,我們要知道線程被中斷一定會(huì)伴隨著一系列的中斷處理操作(這個(gè)我之前的文章里面有詳細(xì)講過(guò)這里就不一一介紹了)這樣子的話會(huì)進(jìn)行不必要的處理操作,所以在異常拋出之前就會(huì)清除中斷狀態(tài)保證異常是真正被中斷的時(shí)候拋出,這是為了線程在異常處理之后能夠正確地繼續(xù)執(zhí)行。
? ? ? ? 我這里還要強(qiáng)調(diào)一點(diǎn)不要把清除中斷狀態(tài)和恢復(fù)中斷狀態(tài)搞混,清除中斷狀態(tài)是在拋出異常之前系統(tǒng)自動(dòng)進(jìn)行的,恢復(fù)中斷狀態(tài)是需要在catch塊當(dāng)中手動(dòng)進(jìn)行的,恢復(fù)中斷狀態(tài)是為了中斷信息得以繼續(xù)傳遞,通過(guò)清除線程的中斷狀態(tài)并且在適當(dāng)?shù)臅r(shí)候恢復(fù)它,使得線程可以在異常處理后繼續(xù)執(zhí)行,并且其他部分的代碼可以根據(jù)需要處理中斷請(qǐng)求。(這部分內(nèi)容作為了解即可)
? ? ? ? 3、Thread(Runnable target, String name)
? ? ? ? 這里其實(shí)就是給線程起一個(gè)名字,內(nèi)容很簡(jiǎn)單直接為大家用代碼演示。
public class Main { public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0;i < 5;i++){ System.out.println(Thread.currentThread().getName() + "running task"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }; Thread thread = new Thread(runnable,"Thread-1"); Thread thread1 = new Thread(runnable,"Thread-2"); thread1.start(); thread.start(); } }
? ? ? ? Thread主要的幾個(gè)構(gòu)造方法就為大家介紹到這里,文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-855259.html
二、其它方法
? ? ? ? 后續(xù)的方法下一篇文章接著為大家介紹,希望這篇文章能夠讓你有所收獲,我們明天再見(jiàn)!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-855259.html
到了這里,關(guān)于【JavaEE多線程】Thread類及其常見(jiàn)方法(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!