???? 看了"臧圩人"的一片多線程文章,根據(jù)自己的想法才寫出這篇過于java 多線程的文章。
一、怎樣實(shí)現(xiàn)多線程:
?????? 1.1實(shí)現(xiàn)多線程:
???????????? 1.1.1、實(shí)現(xiàn)線程的方式有兩種:
??????????????? 1、繼承java.lang.Thread,并重寫它的run()方法,將線程的執(zhí)行主體放入其中。
??????????????? 2、實(shí)現(xiàn)java.lang.Runnable接口,實(shí)現(xiàn)它的run()方法,并將線程的執(zhí)行主體放入其中。
???????????? 1.1.2、這是繼承Thread類實(shí)現(xiàn)線程的示例:
- public ? class ?ThreadTest? extends ?Thread?{ ??
- ???? public ? void ?run()?{ ??
- ???????? //?在這里編寫線程執(zhí)行的主體 ??
- ???????? //?do?something ??
- ????} ??
- }??
public class ThreadTest extends Thread { public void run() { // 在這里編寫線程執(zhí)行的主體 // do something } }
這是實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)多線程的示例:
- public ? class ?RunnableTest? implements ?Runnable?{ ??
- ???? public ? void ?run()?{ ??
- ???????? //?在這里編寫線程執(zhí)行的主體 ??
- ???????? //?do?something ??
- ????} ??
- }??
public class RunnableTest implements Runnable { public void run() { // 在這里編寫線程執(zhí)行的主體 // do something } }
???? 1.1.3這兩種實(shí)現(xiàn)方式的區(qū)別:
??????????繼承Thread類的方式實(shí)現(xiàn)起來較為簡(jiǎn)單,但是繼承它的類就不能再繼承別的類了,因此也就不能繼承別的類的有用的方法了。而使用是想Runnable接口的方式就不存在這個(gè)問題了,而且這種實(shí)現(xiàn)方式將線程主體和線程對(duì)象本身分離開來,邏輯上也較為清晰,所以推薦大家更多地采用這種方式。
??????1.2、啟動(dòng)多線程:
?????? 線程啟動(dòng)的原理是:當(dāng)線程對(duì)象被創(chuàng)建后,通過調(diào)用線程對(duì)象的start()方法來啟動(dòng)線程。因此可以知道,我們通過以上兩種方式實(shí)現(xiàn)了一個(gè)線程之后,線程的實(shí)例并沒有被創(chuàng)建,因此它們也并沒有被運(yùn)行。我們要啟動(dòng)一個(gè)線程,必須調(diào)用方法來啟動(dòng)它,這個(gè)方法就是Thread類的start()方法,而不是run()方法(既不是我們繼承Thread類重寫的run()方法,也不是實(shí)現(xiàn)Runnable接口的run()方法)。run()方法中包含的是線程的主體,也就是這個(gè)線程被啟動(dòng)后將要運(yùn)行的代碼,它跟線程的啟動(dòng)沒有任何關(guān)系。上面兩種實(shí)現(xiàn)線程的方式在啟動(dòng)時(shí)會(huì)有所不同。
繼承Thread類的啟動(dòng)方式: 運(yùn)行線程的大體思路是 在運(yùn)行的程序中添加進(jìn)程對(duì)象,然后調(diào)用start()方法。
- public ? class ?ThreadStartTest?{ ??
- ???? public ? static ? void ?main(String[]?args)?{ ??
- ???????? //?創(chuàng)建一個(gè)線程實(shí)例 ??
- ????????ThreadTest?tt?=? new ?ThreadTest(); ??
- ???????? //?啟動(dòng)線程 ??
- ????????tt.start(); ??
- ????} ??
- }??
public class ThreadStartTest { public static void main(String[] args) { // 創(chuàng)建一個(gè)線程實(shí)例 ThreadTest tt = new ThreadTest(); // 啟動(dòng)線程 tt.start(); } }
實(shí)現(xiàn)Runnable接口的啟動(dòng)方式:
- public ? class ?RunnableStartTest?{ ??
- ???? public ? static ? void ?main(String[]?args)?{ ??
- ???????? //?創(chuàng)建一個(gè)線程實(shí)例 ??
- ????????Thread?t?=? new ?Thread( new ?RunnableTest()); ??
- ???????? //?啟動(dòng)線程 ??
- ????????t.start(); ??
- ????} ??
- }??
?? 1.2.1、?進(jìn)程運(yùn)行的原理
???????? 當(dāng)我們采用實(shí)現(xiàn)Runnable接口的方式來實(shí)現(xiàn)線程的情況下,在調(diào)用new Thread(Runnable target)構(gòu)造器時(shí),將實(shí)現(xiàn)Runnable接口的類的實(shí)例設(shè)置成了線程要執(zhí)行的主體所屬的目標(biāo)對(duì)象target,當(dāng)線程啟動(dòng)時(shí),這個(gè)實(shí)例的run()方法就被執(zhí)行了。當(dāng)我們采用繼承Thread的方式實(shí)現(xiàn)線程時(shí),線程的這個(gè)run()方法被重寫了,所以當(dāng)線程啟動(dòng)時(shí),執(zhí)行的是這個(gè)對(duì)象自身的run()方法。總結(jié)起來就一句話,線程類有一個(gè)Runnable類型的target屬性,它是線程啟動(dòng)后要執(zhí)行的run()方法所屬的主體,如果我們采用的是繼承Thread類的方式,那么這個(gè)target就是線程對(duì)象自身,如果我們采用的是實(shí)現(xiàn)Runnable接口的方式,那么這個(gè)target就是實(shí)現(xiàn)了Runnable接口的類的實(shí)例。
備注:
二、線程的狀態(tài):
??????在Java 1.4及以下的版本中,每個(gè)線程都具有新建、可運(yùn)行、阻塞、死亡四種狀態(tài),但是在Java 5.0及以上版本中,線程的狀態(tài)被擴(kuò)充為新建、可運(yùn)行、阻塞、等待、定時(shí)等待、死亡六種。線程的狀態(tài)完全包含了一個(gè)線程從新建到運(yùn)行,最后到結(jié)束的整個(gè)生命周期。線程狀態(tài)的具體信息如下:
- NEW(新建狀態(tài)、初始化狀態(tài)): 線程對(duì)象已經(jīng)被創(chuàng)建,但是還沒有被啟動(dòng)時(shí)的狀態(tài)。這段時(shí)間就是在我們調(diào)用new命令之后,調(diào)用start()方法之前。
- RUNNABLE(可運(yùn)行狀態(tài)、就緒狀態(tài)): 在我們調(diào)用了線程的start()方法之后線程所處的狀態(tài)。處于RUNNABLE狀態(tài)的線程在JAVA虛擬機(jī)(JVM)上是運(yùn)行著的,但是它可能還正在等待操作系統(tǒng)分配給它相應(yīng)的運(yùn)行資源以得以運(yùn)行。
- BLOCKED(阻塞狀態(tài)、被中斷運(yùn)行): 線程正在等待其它的線程釋放同步鎖,以進(jìn)入一個(gè)同步塊或者同步方法繼續(xù)運(yùn)行;或者它已經(jīng)進(jìn)入了某個(gè)同步塊或同步方法,在運(yùn)行的過程中它調(diào)用了某個(gè)對(duì)象繼承自java.lang.Object的wait()方法,正在等待重新返回這個(gè)同步塊或同步方法。
- WAITING(等待狀態(tài)): 當(dāng)前線程調(diào)用了java.lang.Object.wait()、java.lang.Thread.join()或者java.util.concurrent.locks.LockSupport.park()三個(gè)中的任意一個(gè)方法,正在等待另外一個(gè)線程執(zhí)行某個(gè)操作。比如一個(gè)線程調(diào)用了某個(gè)對(duì)象的wait()方法,正在等待其它線程調(diào)用這個(gè)對(duì)象的notify()或者notifyAll()(這兩個(gè)方法同樣是繼承自O(shè)bject類)方法來喚醒它;或者一個(gè)線程調(diào)用了另一個(gè)線程的join()(這個(gè)方法屬于Thread類)方法,正在等待這個(gè)方法運(yùn)行結(jié)束。
- TIMED_WAITING(定時(shí)等待狀態(tài)): 當(dāng)前線程調(diào)用了java.lang.Object.wait(long timeout)、java.lang.Thread.join(long millis)、java.util.concurrent.locks.LockSupport.packNanos(long nanos)、java.util.concurrent.locks.LockSupport.packUntil(long deadline)四個(gè)方法中的任意一個(gè),進(jìn)入等待狀態(tài),但是與WAITING狀態(tài)不同的是,它有一個(gè)最大等待時(shí)間,即使等待的條件仍然沒有滿足,只要到了這個(gè)時(shí)間它就會(huì)自動(dòng)醒來。
- TERMINATED(死亡狀態(tài)、終止?fàn)顟B(tài)): 線程完成執(zhí)行后的狀態(tài)。線程執(zhí)行完run()方法中的全部代碼,從該方法中退出,進(jìn)入TERMINATED狀態(tài)。還有一種情況是run()在運(yùn)行過程中拋出了一個(gè)異常,而這個(gè)異常沒有被程序捕獲,導(dǎo)致這個(gè)線程異常終止進(jìn)入TERMINATED狀態(tài)。
?
???? 1、線程中常見概念:
?????????? 1、線程主題
???????????2、線程對(duì)象
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
