一、進程:多線程
進程是程序的一次動態執行過程。用進程來對應一個程序,每一個進程對應必定的內存地址空間,而且只能使用它本身的內存空間,各個進程間互不干擾。ide
二、線程:測試
線程是程序內部的控制流,比進程更小的執行單位,是進程內部的子任務。一個進程在執行過程當中,爲了同時完成多個操做,能夠產生多個線程,造成多條執行線索。ui
三、進程與線程的區別:spa
(1)、每一個進程有一段專有內存空間。進程各自佔有不一樣空間,內存消耗很大,會形成系統在不一樣程序之間切換時開銷很大,進程之間通訊速度很慢。.net
(2)、同一進程的各線程之間共享相同內存空間,利用共享內存來實現數據交換、實時通訊及必要的同步工做。線程之間通訊速度快,相互切換所佔系統資源也小。線程
在Java中,線程的建立通常有2種方式:1.繼承Thread類 ;2.實現Runnable接口。對象
示例代碼:blog
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package
com.model.elgin.thread; public class TestThread1 { public static void main( String [] args) { MyThread mt1= new MyThread(); MyThread mt2= new MyThread(); //setName方法爲線程命名 mt1.setName( "mt1" ); mt2.setName( "mt2" );; //start方法開啓線程 mt1.start(); mt2.start(); } } class MyThread extends Thread{ @Override public void run() { for ( int i = 0 ; i < 10 ; i++) { //currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 System.out.println(Thread.currentThread().getName() + ": Hello thread-" + i); } } } |
運行結果:繼承
從上面的運行結果能夠看出:2個線程在同時運行,爭奪CPU資源,並無前後的優先級,若是再次運行一次,那麼會獲得不一樣的順序結果。
示例代碼:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package
com.model.elgin.thread; public class TestThread2 { public static void main( String [] args) { //聲明一個資源類實例 RunThread rt= new RunThread(); //將此實例傳入Thread構造方法,建立線程對象 Thread rmt1= new Thread(rt); rmt1.setName( "rmt1" ); Thread rmt2= new Thread(rt); rmt2.setName( "rmt2" ); rmt1.start(); rmt2.start(); } } //聲明資源類,須要實現Runnable接口,用來建立線程 class RunThread implements Runnable{ @Override public void run() { for ( int i = 0 ; i < 10 ; i++) { //currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 System.out.println(Thread.currentThread().getName() + ": Hello thread-" + i); } } } |
注意,這種方式必須將Runnable做爲Thread類的參數,而後經過Thread的start方法來建立一個新線程來執行該子任務。
若是直接調用Runnable的run方法的話,是不會建立新線程的,這跟普通的方法調用沒有任何區別。
事實上,查看Thread類的實現源代碼會發現Thread類是實現了Runnable接口的。
小結:
在Java中是不支持多繼承的,若是一個類已經繼承了另外一個類,那麼它就不能經過繼承Thread類來實現多線程操做,這時候就可使用第二種方式,也就是實現Runable接口來實現。由於Java是單繼承,多實現的。另外一個方面說,若是一個類已經繼承Thread了,那麼它就沒法繼承其餘類去實現更復雜的功能,因此多線程的實現推薦使用實現Runable接口的方式。
#上面2個例子中已使用過
public static native Thread currentThread() 返回當前活動線程的引用;
public static native void yield() 使當前執行線程暫時中止執行而讓其餘線程執行;
示例:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package
com.model.elgin.thread; public class TestThread1 { public static void main( String [] args) { MyThread mt1= new MyThread(); MyThread1 mt2= new MyThread1(); //setName方法爲線程命名 mt1.setName( "mt1" ); mt2.setName( "mt2" );; //start方法開啓線程 mt1.start(); mt2.start(); } } class MyThread extends Thread{ @Override public void run() { for ( int i = 0 ; i < 10 ; i++) { //currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 System.out.println(Thread.currentThread().getName() + ": Hello thread1-" + i); } } } class MyThread1 extends Thread{ @Override public void run() { //調用yield方法使當前線程暫停等其它線程執行完畢以後再執行它 //Thread.yield(); for ( int i = 0 ; i < 10 ; i++) { //currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 System.out.println(Thread.currentThread().getName() + ": Hello thread2-" + i); } } } |
結果對比:
左邊爲未打開34行註釋的結果(即未調用yield方法),右邊是調用yield的結果
public static native void sleep(long millis) throws InterruptedException 使當前活動線程睡眠指定的時間millisme;
public static void sleep(long millis,int nanos)throws InterruptedException 使當前活動線程睡眠指定的時間millisme加上十萬分之nanos秒;
public native synchronized void start() 開始運行當前線程;
public void run() 該方法用來定義線程體。一旦線程被啓動執行,就開始執行這個方法;
public final native boolean isAlive() 測試當前線程是否在活動;
#---------@Deprecated註解方法開始,不鼓勵使用-----------#
public final void stop() 強制當前線程中止運行,並拋出ThreadDead錯誤;
public void destroy() 撤消當前線程;
public final void suspend() 臨時掛起當前線程;
public final void resume() 恢復運行掛起的線程;
#---------@Deprecated註解方法結束,不鼓勵使用-----------#
public final void setPriority(int newPriouity) 設置線程的優先級
能夠在MIN_PRIORITY、NORM_PRIORIITY和MAX_PRIORITY之間,通常MIN_PRIORITY爲1,MAX_PRIORITY爲10;
public final int getPriority() 得到當前線程的優先級;
public final void setName(String name) 設置線程名;
public final String getName() 獲得當前線程名;
public final ThreadGroup getThreadGroup( ) 返回當前的線程組;
小結:
Thread提供的控制線程的主要方法:
後續將結合線程的生命週期來介紹上述的幾個重點方法