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

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