文章目錄
創建新線程
繼承Thread類重寫run方法
package example;
public class Work extends Thread {
@Override
public void run() {
super.run();
System.out.println("new thread start");
}
}
也可以直接寫在創建處
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
super.run();
System.out.println("new thread start");
}
};
thread.start();
}
}
用Lambda表達式可以簡寫這一過程
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("new thread start");
});
thread.start();
}
}
實現 Runnable 接口,重寫 run 方法,作爲參數傳入Thread()
package example;
public class Work implements Runnable {
@Override
public void run() {
System.out.println("new thread start");
}
}
或者直接在參數裏創建
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new thread start");
}
});
thread.start();
}
}
Thread 構造方法參數
private Thread(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals)
- ThreadGroup g:線程組
- Runnable target:要執行的任務
- String name:線程名
Thread 常用方法
currentThread()
靜態方法,返回對當前正在執行的線程對象的引用
start()
在原線程執行,啓動新線程,接着會在新線程內自動執行 run() 方法,一個線程只能執行一次 start()
方法
yield()
指當前線程願意讓出對當前處理器的佔用
sleep()
靜態方法,使當前線程掛起一段時間
join()
使當前線程等待另一個線程執行完畢之後再繼續執行
setPriority(int n)
靜態方法,設置線程的優先級,供操作系統調度使用
線程的狀態
- New:新創建的線程,尚未執行;
- Runnable:運行中的線程,正在執行
run()
方法的Java代碼; - Blocked:運行中的線程,因爲某些操作被阻塞而掛起;
- Waiting:運行中的線程,因爲某些操作在等待中;
- Object.wait():使當前線程處於等待狀態直到另一個線程喚醒它;
- Thread.join():等待線程執行完畢,底層調用的是Object實例的wait方法;
- LockSupport.park():除非獲得調用許可,否則禁用當前線程進行線程調度。
- Timed Waiting:運行中的線程,因爲執行
sleep()
方法正在計時等待;- Thread.sleep(long millis):使當前線程睡眠指定時間;
- Object.wait(long timeout):線程休眠指定時間,等待期間可以通過
notify()/notifyAll()
喚醒; - Thread.join(long millis):等待當前線程最多執行
millis
毫秒,如果millis
爲0,則會一直執行; - LockSupport.parkNanos(long nanos): 除非獲得調用許可,否則禁用當前線程進行線程調度指定時間;
- LockSupport.parkUntil(long deadline):同上,也是禁止線程進行調度指定時間;
- Terminated:線程已終止,因爲
run()
方法執行完畢。
可以使用 getState()
方法查看線程狀態,這個方式只是給用戶提供一個查看線程狀態的方法,並不能用來進行線程同步控制
package example;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new thread start");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(thread.getState());
//NEW
thread.start();
System.out.println(thread.getState());
//RUNNABLE
Thread.sleep(1000);
System.out.println(thread.getState());
//TIMED_WAITING
thread.join();
System.out.println(thread.getState());
//TERMINATED
}
}
守護線程
對於一般線程,如果線程沒有結束,那麼JVM就不會結束
而對於守護線程,當所有非守護線程結束,就算守護線程沒結束,JVM也會結束
守護線程需要在線程啓動前,由線程的引用調用 setDaemon(true)
來設置
package example;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
try {
Thread.sleep(100000);
System.out.println("after sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.setDaemon(true);
thread.start();
}
}
運行程序會發現程序立即結束,沒有打印任何信息,顯然程序並沒有等待守護線程結束
中斷線程
使用 interrupt() 方法通知線程結束
對於線程 t,其他線程如果調用 t.interrupt()
方法,在線程 t 內,isInterrupted()
就會返回true,通知線程結束操作
如果線程處於等待,如在調用 join()
等待其他線程執行,join
會拋出 InterruptedException
異常,此時只要捕獲到該異常,也就收到了結束線程的通知
使用共享變量通知
在線程內,可以定義一個共享變量,供其他線程使用通知結束信號
public volatile boolean interupt = false;
volatile 關鍵字告訴JVM要立刻更新內存中的信息