從今天開始開始多了解一些Java多線程的有關知識,自己在腦海中好好做個整理,Java多線程也是一個十分容易出問題的地方。在簡書中看見一位大牛推薦的Java多線程書籍《Java多線程編程核心技術》,這本書感覺還不錯,適合自己,就從這里開始吧。
[TOC]
Thread常用方法
方法名稱 | 方法作用 |
---|---|
currentThread(靜態) | 返回對當前正在執行的線程對象的引用 |
isAlive | 判斷當前的線程是否處于活動狀態
|
sleep(靜態) | 讓當前正在執行的線程休眠 |
getId | 取得線程的唯一標識 |
** 注意:** 活動狀態是指線程已經啟動且尚未終止。
告訴你真相:
class MyThread extends Thread{
public MyThread(){
System.out.println("thread name = " + Thread.currentThread().getName());
}
public void run(){
System.out.println("thread name = " + Thread.currentThread().getName());
}
}
public class Demo{
public static void main(String[] args) throws Exception{
MyThread thread = new MyThread();
thread.start();
}
}
運行結果:
thread name = main
thread name = Thread-0
這里主要說明Thread的實例化是在主線程中進行的,只有run方法會在自己的線程中自動被調用。
知道了一種比較好用的停止線程手段。開心ing(interrupt 英 [?nt?'r?pt] 中斷 我去!又是個難記得word)
在實現之前先了解下Thread類的三個方法
方法名稱 | 方法作用 |
---|---|
interrupt | 中斷線程 |
interrupted(靜態) | 測試當前線程是否已經是中斷狀態,執行后具有將狀態標志清除為false的功能 |
isInterrupted | 測試線程Thread對象是否已經是中斷狀態,但是不清楚狀態標志 |
class MyThread extends Thread{
public void run(){
try{
for(int i = 0; i < 1000000; i++){
if (Thread.interrupted()) { // 判斷當前線程是否中斷
throw new InterruptedException();
}
System.out.println("i = " + i);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class Demo{
public static void main(String[] args) throws Exception{
MyThread thread = new MyThread();
thread.start();
Thread.sleep(10);
thread.interrupt(); // 停止線程
}
}
運行結果:
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10
i = 11
i = 12
i = 13
i = 14
i = 15
i = 16
i = 17
i = 18
i = 19
i = 20
java.lang.InterruptedException
at MyThread.run(Demo.java:10)
啊哈就這么簡單的實現了線程的停止,而且用異常的方式還可以將信息傳遞回去,這樣是不是very nice?。
Java多線程的優先級(Priority 吐槽一下,這詞真難記)
啊哦,Java多線程具有哪些特色呢?(小二,優先級有啥特色,快快拿來嘗嘗鮮)
- 繼承特性(這里可不是說誰繼承誰,它要說明的是當一個線程啟動另一個線程的默認情況下,它們的優先級一樣)
- 規則性(同時執行的多個線程,優先級大的線程先被執行的可能性更高)
- 隨機性(表示并不一定優先級高,就一定先執行它)
繼承特性Test:
class ThreadParent extends Thread{
public void run(){
System.out.println("ThreadParent priority = " +this.getPriority());
this.setPriority(8); // 這里有故事
ThreadChild childThread = new ThreadChild();
childThread.start();
}
}
class ThreadChild extends Thread{
public void run(){
System.out.println("ThreadChild priority = " +this.getPriority());
}
}
public class Demo{
public static void main(String[] args) throws Exception{
System.out.println("main Thread priority start = " + Thread.currentThread().getPriority());
Thread.currentThread().setPriority(6);
System.out.println("main Thread priority end = " + Thread.currentThread().getPriority());
ThreadParent thread = new ThreadParent();
thread.start();
}
}
Test結果:
main Thread priority start = 5
main Thread priority end = 6
ThreadParent priority = 6
ThreadChild priority = 8
可以看到事實確實如此。不過這里我測試發現,當一個線程啟動另一個線程的時候,它的優先級是在實例化另一個線程的時候完成的。因為如果你將上面的第四行this.setPriority(8)
放到第五行下面,你會發現ThreadChild的優先級還是6。(具體的為什么就需要你去發掘啦~)
Java多線程有倆種
- 用戶線程
- 守護線程(daemon 這是個新單詞哦(發音:英 ['di?m?n] (迪們)))
守護線程最大的特點就是,只有當 所有的非守護線程Over 了,它才會Over。
書中舉了個最好的例子就是Java的垃圾回收器是個守護線程。
那我們如何讓一個線程變成守護線程呢?
非常簡單,只需要調用Thread
實例的setDaemon()
。
接下來用代碼說話!
class MyRunnable implements Runnable{
public void run(){
while(true){ // 這里寫了一個死循環
for (int i = 0; i < 5; i++) {
System.out.println("I am DaemonThread: "+Thread.currentThread().getName());
}
}
}
}
public class Demo{
public static void main(String[] args) throws Exception{
MyRunnable runable = new MyRunnable();
Thread myThread = new Thread(runable);
myThread.setDaemon(true); // 將線程設置為守護線程
myThread.start();
Thread.sleep(1000);
System.out.println("MainThread Over!");
}
}
輸出結果:
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
I am DaemonThread: Thread-0
MainThread Over!
I am DaemonThread: Thread-0
從上面的代碼中我們可以看到守護線程要執行的是一個無線循環,如果是用戶線程它將會一直執行下去,但是守護線程則不同。main線程執行完后,守護線程也GG了。