作個筆記,java線程經常使用的方法,耐心看完.javascript
編號 | 方法 | 說明 |
---|---|---|
1 | public void start() |
使該線程開始執行;Java 虛擬機調用該線程的 run 方法。 |
2 | public void run() |
若是該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;不然,該方法不執行任何操做並返回。 |
3 | public final void setName(String name) |
改變線程名稱,使之與參數 name 相同。 |
4 | public final void setPriority(int priority) |
更改線程的優先級。 |
5 | public final void setDaemon(boolean on) |
將該線程標記爲守護線程或用戶線程。 |
6 | public final void join(long millisec) |
等待該線程終止的時間最長爲 millis 毫秒。 |
7 | public void interrupt() |
中斷線程。 |
8 | public final boolean isAlive() |
測試線程是否處於活動狀態。 |
9 | public static void yield() |
暫停當前正在執行的線程對象,並執行其餘線程。 |
10 | public static void sleep(long millisec) |
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操做受到系統計時器和調度程序精度和準確性的影響。 |
11 | public static Thread currentThread() |
返回對當前正在執行的線程對象的引用。 |
currentThread()方法能夠返回代碼段正在被哪一個線程調用的信息。java
public class Run1{ public static void main(String[] args){ System.out.println(Thread.currentThread().getName()); } }
方法sleep()的做用是在指定的毫秒數內讓當前「正在執行的線程」休眠(暫停執行)。這個「正在執行的線程」是指this.currentThread()返回的線程。面試
sleep方法有兩個重載版本:多線程
sleep(long millis) //參數爲毫秒 sleep(long millis,int nanoseconds) //第一參數爲毫秒,第二個參數爲納秒
sleep至關於讓線程睡眠,交出CPU,讓CPU去執行其餘的任務。
可是有一點要很是注意,sleep方法不會釋放鎖,也就是說若是當前線程持有對某個對象的鎖,則即便調用sleep方法,其餘線程也沒法訪問這個對象。看下面這個例子就清楚了:ide
public class Test { private int i = 10; private Object object = new Object(); public static void main(String[] args) throws IOException { Test test = new Test(); MyThread thread1 = test.new MyThread(); MyThread thread2 = test.new MyThread(); thread1.start(); thread2.start(); } class MyThread extends Thread{ @Override public void run() { synchronized (object) { i++; System.out.println("i:"+i); try { System.out.println("線程"+Thread.currentThread().getName()+"進入睡眠狀態"); Thread.currentThread().sleep(10000); } catch (InterruptedException e) { // TODO: handle exception } System.out.println("線程"+Thread.currentThread().getName()+"睡眠結束"); i++; System.out.println("i:"+i); } } } }
從上面輸出結果能夠看出,當Thread-0進入睡眠狀態以後,Thread-1並無去執行具體的任務。只有當Thread-0執行完以後,此時Thread-0釋放了對象鎖,Thread-1纔開始執行。測試
注意,若是調用了sleep方法,必須捕獲InterruptedException異常或者將該異常向上層拋出。當線程睡眠時間滿後,不必定會當即獲得執行,由於此時可能CPU正在執行其餘的任務。因此說調用sleep方法至關於讓線程進入阻塞狀態。this
調用yield方法會讓當前線程交出CPU權限,讓CPU去執行其餘的線程。它跟sleep方法相似,一樣不會釋放鎖。可是yield不能控制具體的交出CPU的時間,另外,yield方法只能讓擁有相同優先級的線程有獲取CPU執行時間的機會。spa
注意,調用yield方法並不會讓線程進入阻塞狀態,而是讓線程重回就緒狀態,它只須要等待從新獲取CPU執行時間,這一點是和sleep方法不同的。
代碼:操作系統
public class MyThread extends Thread{ @Override public void run() { long beginTime=System.currentTimeMillis(); int count=0; for (int i=0;i<50000000;i++){ count=count+(i+1); //Thread.yield(); } long endTime=System.currentTimeMillis(); System.out.println("用時:"+(endTime-beginTime)+" 毫秒!"); } } public class Run { public static void main(String[] args) { MyThread t= new MyThread(); t.start(); } } //用時:3 毫秒! //若是將 Thread.yield();的註釋去掉,執行結果以下: 用時:16080 毫秒!
start()用來啓動一個線程,當調用start方法後,系統纔會開啓一個新的線程來執行用戶定義的子任務,在這個過程當中,會爲相應的線程分配須要的資源。線程
run()方法是不須要用戶來調用的,當經過start方法啓動一個線程以後,當線程得到了CPU執行時間,便進入run方法體去執行具體的任務。注意,繼承Thread類必須重寫run方法,在run方法中定義具體要執行的任務。
getId()的做用是取得線程的惟一標識
public class Test { public static void main(String[] args) { Thread t= Thread.currentThread(); System.out.println(t.getName()+" "+t.getId()); } } //main 1
方法isAlive()的功能是判斷當前線程是否處於活動狀態
public class MyThread extends Thread{ @Override public void run() { System.out.println("run="+this.isAlive()); } } public class RunTest { public static void main(String[] args) throws InterruptedException { MyThread myThread=new MyThread(); System.out.println("begin =="+myThread.isAlive()); myThread.start(); System.out.println("end =="+myThread.isAlive()); } } //begin ==false //run=true //end ==false
方法isAlive()的做用是測試線程是否偶處於活動狀態。什麼是活動狀態呢?活動狀態就是線程已經啓動且還沒有終止。線程處於正在運行或準備開始運行的狀態,就認爲線程是「存活」的。
有個須要注意的地方
System.out.println("end =="+myThread.isAlive());
雖然上面的實例中打印的值是true,但此值是不肯定的。打印true值是由於myThread線程還未執行完畢,因此輸出true。若是代碼改爲下面這樣,加了個sleep休眠:
public static void main(String[] args) throws InterruptedException { MyThread myThread=new MyThread(); System.out.println("begin =="+myThread.isAlive()); myThread.start(); Thread.sleep(1000); System.out.println("end =="+myThread.isAlive()); }
則上述代碼運行的結果輸出爲false,由於mythread對象已經在1秒以內執行完畢。
在不少狀況下,主線程建立並啓動了線程,若是子線程中藥進行大量耗時運算,主線程每每將早於子線程結束以前結束。這時,若是主線程想等待子線程執行完成以後再結束,好比子線程處理一個數據,主線程要取得這個數據中的值,就要用到join()方法了。方法join()的做用是等待線程對象銷燬。
public class Thread4 extends Thread{ public Thread4(String name) { super(name); } public void run() { for (int i = 0; i < 5; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) throws InterruptedException { // 啓動子進程 new Thread4("new thread").start(); for (int i = 0; i < 10; i++) { if (i == 5) { Thread4 th = new Thread4("joined thread"); th.start(); th.join(); } System.out.println(Thread.currentThread().getName() + " " + i); } } } /* main 0 main 1 main 2 main 3 main 4 new thread 0 new thread 1 new thread 2 new thread 3 new thread 4 joined thread 0 joined thread 1 joined thread 2 joined thread 3 joined thread 4 main 5 main 6 main 7 main 8 main 9 由上能夠看出main主線程等待joined thread線程先執行完了才結束的。若是把th.join()這行註釋掉,運行結果以下: main 0 main 1 main 2 main 3 main 4 main 5 main 6 main 7 main 8 main 9 new thread 0 new thread 1 new thread 2 new thread 3 new thread 4 joined thread 0 joined thread 1 joined thread 2 joined thread 3 joined thread 4 */
用來獲得或者設置線程名稱。
用來獲取和設置線程優先級。此方法不經常使用,這種方式不可靠
用來設置線程是否成爲守護線程和判斷線程是不是守護線程。
守護線程和用戶線程的區別在於:守護線程依賴於建立它的線程,而用戶線程則不依賴。舉個簡單的例子:若是在main線程中建立了一個守護線程,當main方法運行完畢以後,守護線程也會隨着消亡。而用戶線程則不會,用戶線程會一直運行直到其運行完畢。在JVM中,像垃圾收集器線程就是守護線程。
答:一個進程是一個獨立(self contained)的運行環境,它能夠被看做一個程序或者一個應用。而線程是在進程中執行的一個任務。線程是進程的子集,一個進程能夠有不少線程,每條線程並行執行不一樣的任務。不一樣的進程使用不一樣的內存空間,而全部的線程共享一片相同的內存空間。別把它和棧內存搞混,每一個線程都擁有單獨的棧內存用來存儲本地數據。
答:建立線程有兩種方式:
1、繼承 Thread 類,擴展線程。
2、實現 Runnable 接口。
答:啓動一個線程是調用start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由JVM 調度並執行,這並不意味着線程就會當即運行。run()方法是線程啓動後要進行回調(callback)的方法
答:sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其餘線程,可是對象的鎖依然保持,所以休眠時間結束後會自動恢復。wait()是Object類的方法,調用對象的wait()方法致使當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),若是線程從新得到對象的鎖就能夠進入就緒狀態。
答:
① sleep()方法給其餘線程運行機會時不考慮線程的優先級,所以會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;
② 線程執行sleep()方法後轉入阻塞(blocked)狀態,而執行yield()方法後轉入就緒(ready)狀態;
③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;
④ sleep()方法比yield()方法(跟操做系統CPU調度相關)具備更好的可移植性。
小夥伴一塊兒加油吧