做者 : Stanley 羅昊java
【轉載請註明出處和署名,謝謝!】linux
在理解多線程以前,咱們先須要瞭解什麼是進程?編程
進程說白了就是在你的內存空間中開闢出的一個獨立的空間;windows
若是還不理解的話,我再解釋一下;多線程
想必各位以前都安裝過軟件吧,你安裝完軟件以後,在你的軟件安裝包裏面是否是有一個.exe文件,那你雙擊exe文件的時候,在你的任務管理器,在裏面就有一個進程選項卡,就是說,每當你打開一個exe文件的時候,它都會顯示在任務管理器的進程當中,因此就能夠把運行中的任意一款軟件,均可以把它看作一個進程;併發
固然,以上的操做方式是在windows系統的操做的,也就是說,想查看Windows的進程,只須要在任務管理器中查看便可;測試
在linux下使用命令 ps 或 pstree、ps -eflgrep;spa
若是想在linux系統下查看java的相關進程,命令爲:jps;操作系統
那麼問題就來了,當你打開QQ的時候,是否是就是開啓了一個進程,當你開始使用它而且聊天的時候,好比你是a,你如今要跟b聊自然後再去跟c聊天,那麼這樣的操做是否是相互獨立的呢?也就是說,你如今要跟b發送你的遊戲密碼,這個時候c問你晚上吃啥飯,你發的密碼c知道嗎?確定不會啦,因此你跟b聊天的時候,是不會影響你跟c聊天的,由於你跟b c 是相互獨立的;線程
那麼,在這個裏面,你跟他們每一個人產生的通話底層是怎麼實現的呢?
底層就是靠線程去實現的;
什麼是線程呢?
線程是指程序在執行過程當中,可以執行程序代碼的一個執行單元,在Java語言中,線程有四種狀態:運行,就緒,掛起,結束。通常狀況下,一個操做系統是有多個進程,那麼每一個進程都要對應多個線程;
線程與進程有區別嗎?
有,進程是一段正在運行的程序,而線程有時也被稱爲輕量級進程,它是進程的執行單元,一個進程能夠擁有多個線程,各個線程之間共享程序的內存空間,可是,各個線程擁有本身的棧空間。
一個進程能夠有不少線程,每條線程並行執行不一樣的任務;
在以前的一些簡單的java練習中,咱們運行的時候,是否是都是在main方法中測試運行啊,那麼,在這以前,我僅僅編寫了一些很是簡單的java代碼,甚至就在main方法中輸出了一句話,就能夠直接完成運行,在這期間,我並無建立有關線程方面的方法以及程序,那麼就怎麼實現運行了呢?
其實很簡單,Main方法既然能運行你的程序,那麼必然就會有一個線程,那麼這個線程就是單線程,那,咱們如何查看本次運行線程的線程名呢?
咱們僅需在main方法裏面輸出如下便可:
System.out.println(Thread.currentThread());
打印出來後,咱們就能夠看到線程名師Main,由於就一個線程,因此main就是主線程;
那麼就一個線程,就代表,在這以前,咱們所作的一些練習程序都是單線程的;
兩種:
1.繼承(extends) Thread
繼承完Thread類以後須要重寫run方法;
2.實現(implem) Runnable接口
也許須要重寫run方法;
講了那麼多,那麼就開始上手實操一下,咱們將要練習的是繼承Thread來建立一個線程;
首先,咱們建立一個類(MyThread)而後繼承Thread類;
繼承完Thread後,實現run方法;
run方法的做用就是,至關於這個線程對用戶提供的一個接口;
因此,用戶有什麼業務邏輯,都須要寫在run方法裏面:
public class MyThread extends Thread{ public void run(){ //做用:至關於這個線程向用戶提供的接口,用戶有什麼樣的業務邏輯,寫在這個方法中 } }
那咱們如今就讓這個run方法就實現一個簡單的打印;
這個就是我使用了第一種方式來建立了一個線程;
那麼,你這個線程建立完成後,若是你想調用它怎麼辦?
我再建一個類(TestThread);
而後提供一個Main方法;
在main方法中建立一個線程,語法:
//建立一個線程 MyThread mt = new MyThred();
這個就是建立線程,建立完後,下一步咱們須要調用start方法;
public class TestThread{ public static void main (String [] args){ //建立線程 MyThread mt = new MyThred(); //啓動線程 mt.start(); } }
爲何要調用start,而不是run?
其實很簡單,mt.start就是啓動你的線程,那麼啓動後,它底層就會去調用你的run方法;
這個就是線程的啓動式start方法;
咱們運行一下後,看一下控制檯打印:
就是一些輸出,感受就跟調用方法同樣,對吧;
那麼,接下來,咱們看一下第二種建立方式
這種方法跟上面的那種,大同小異,只不過上面那個是繼承,這個是實現接口;
實現Runnable接口後,須要實現它的run方法;
public class MyRunnableThread implements Runable{ public void run(){ //做用:至關於這個線程向用戶提供的接口,用戶有什麼樣的業務邏輯,寫在這個方法中 } }
如今,咱們用第二種方式建立了一個線程,固然,業務邏輯跟上面的那個相同,由於舉例,因此沒有深究別的;
由於運行線程永遠須要Thread裏面的start方法來啓動線程,因此須要把Thread建立出來,再將建立出來的線程放進去;
因此打印出來的結果是跟上面的結果是同樣的,這裏就再也不放圖上去了;
start,是線程啓動的方法;
run方法是線程執行過程當中調用的方法(默認調用),在上面的例子咱們也看到了,你並無手動去調用run方法,是他自動調用的,就跟你建立對象的時候,默認調用構造方法同樣;
那,啓動線程必定是要用staet方法啓動,我試試不用它,我直接調用Thread中的run方法可行嗎?
可行,由於拋開線程,你自己就是實例化了Thread這個類,並調用該類中的run方法是沒有問題的,可是,不歸入線程中!!
咱們直接調用run方法後,發現,方法能夠正常打印,由於,僅僅完成了普通方法的調用,實際上並無啓動線程;