线程
-
Thread 線程
-
一、線程創(chuàng)建的三種方式
- 方式一:繼承Thread類的方式進行實現(xiàn)
- 方式二:實現(xiàn)Runnable接口的方式進行實現(xiàn)
- 方式三:利用Callable接口和Future接口方式實現(xiàn)
- 二、Thread狀態(tài)
- 三、異步ComletableFuture入門
-
一、線程創(chuàng)建的三種方式
Thread 線程
視頻地址:https://www.bilibili.com/video/BV1LG4y1T7n2/?p=5&vd_source=e33a356475cf6a18a9f6345f4e44a209
一、線程創(chuàng)建的三種方式
方式一:繼承Thread類的方式進行實現(xiàn)
- 自己定義一個類繼承Thread,其實Thread也是實現(xiàn)Runnable接口
- 重寫run方法
- 創(chuàng)建子類的對象,并啟動線程
public class MyThread extends Thread {
/**
* * 線程實現(xiàn)的方式一:
* * 1. 自己定義一個類繼承Thread
* * 2. 重寫run方法
* * 3. 創(chuàng)建子類的對象,并啟動線程
*/
private int x = 0;
@Override
public void run() {
// 書寫執(zhí)行代碼
for (int i = 0; i < 10; i++) {
System.out.println(this.getName() + " x : " + (this.x++));
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
// 線程名字可以通過 t.setName() 來設置
t1.setName("線程一");
t2.setName("線程二");
t1.start();
t2.start();
System.out.println("main方法執(zhí)行結束");
}
}
方式二:實現(xiàn)Runnable接口的方式進行實現(xiàn)
- 自己定義一個類實現(xiàn)Runnable接口
- 重寫里面的run方法
- 創(chuàng)建自己類的對象
- 創(chuàng)建一個Thread類的對象,并開啟線程
@NoArgsConstructor
public class MyRunnable implements Runnable {
@Override
public void run() {
// 獲取當前線程的名稱
String strName = Thread.currentThread().getName();
// n值代表循環(huán)多少次
int n = 11;
for (int i = 0; i < n; i++) {
System.out.println("當前線程的名字是:" + strName + ",第" + i + "次執(zhí)行!");
}
}
public static void main(String[] args) {
// 創(chuàng)建myRunnable任務
MyRunnable myRunnable = new MyRunnable();
// 創(chuàng)建線程對象,將任務傳遞給線程
Thread t1 = new Thread(myRunnable);
Thread t2 = new Thread(myRunnable);
t1.setName("線程一");
t2.setName("線程二");
// 開啟線程
t1.start();
t2.start();
}
}
方式三:利用Callable接口和Future接口方式實現(xiàn)
- 創(chuàng)建一個類MyCallable實現(xiàn)Callable接口
- 重寫call(是有返回值的,表示多線程運行的結果)
- 創(chuàng)建MyCallable的對象(表示多線程要執(zhí)行的任務)
- 創(chuàng)建FutureTask對象(作用管理多線程運行的結果)
- 創(chuàng)建Thread類的對象,并啟動(表示線程)
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() {
// 求 1-100的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 創(chuàng)建了一個MyCallable的對象,表示多線程要執(zhí)行的任務
MyCallable callable = new MyCallable();
// 創(chuàng)建FutureTask對象(作用管理多線程運行的結果)
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 創(chuàng)建線程的對象
Thread t1 = new Thread(futureTask);
// 啟動線程
t1.start();
// 獲取多線程運行的結果
Integer result = futureTask.get();
System.out.println(result);
}
}
thread中常見的成員方法:
-
String getName() 返回線程的名稱
-
void setName(String name) 設置線程的名字(構造方法也可以設置名稱)
細節(jié):
1、如果我們沒有給線程設置名字,線程也是默認有名字的 格式:Thread-X(X是序號,從0開始)
2、如果我們要給線程設置名稱,可以用set 方法設置,也可以用構造方法設置 -
static Thread currentThread() 獲取當前線程的對象
細節(jié):
當JVM虛擬機啟動之后,會自動的啟動多線程,其中一條線程叫做main線程,他的作用就是調用main方法,并執(zhí)行里面的代碼,在以前我們寫的所有代碼,其實都在main線程中運行 -
static void sleep(long time) 讓線程休眠指定的時間,單位為毫秒
細節(jié):
1、那條線程執(zhí)行到這個方法,那么哪條線程就會在這里停留對應的時間
2、方法的參數(shù):就表示睡眠的時間,單位毫秒,1秒=1000毫秒
3、當時間到了之后,線程會自動的醒來,繼續(xù)執(zhí)行下面的其他代碼
二、Thread狀態(tài)
- New:新創(chuàng)建的線程,尚未執(zhí)行;
- Runnable:運行中的線程,正在執(zhí)行
run()方法的Java代碼; - Blocked:運行中的線程,因為某些操作被阻塞而掛起;
- Waiting:運行中的線程,因為某些操作在等待中;
- Timed Waiting:運行中的線程,因為執(zhí)行
sleep()方法正在計時等待; - Terminated:線程已終止,因為
run()方法執(zhí)行完畢。
圖示如下:
┌─────────────┐
│ New │
└─────────────┘
│
▼
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
┌─────────────┐ ┌─────────────┐
││ Runnable │ │ Blocked ││
└─────────────┘ └─────────────┘
│┌─────────────┐ ┌─────────────┐│
│ Waiting │ │Timed Waiting│
│└─────────────┘ └─────────────┘│
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│
▼
┌─────────────┐
│ Terminated │
└─────────────┘
線程終止的原因是:
- 線程正常終止:
run()方法執(zhí)行到return語句返回; - 線程意外終止:
run()方法因為未捕獲的異常導致線程終止; - 對某個線程的
Thread實例調用stop()方法強制終止(強烈不推薦使用)。
join():一個線程等待另一個線程,直到等待結束,可以指定等待時間,超過等待時間線程仍然沒有結束就不再等待;
對已經運行結束的線程調用join()方法會立刻返回。
interrupt() 中斷線程,對線程的調用看她是否中斷,isInterrupted()標示獲取自身是否中斷,如果目標線程處于等待狀態(tài),該線程會拋出異常InterruptedException,一般線程處于中斷狀態(tài),應該立刻結束自身線程,線程間共享變量需要使用volatile關鍵字標記,確保每個線程都能讀取到更新后的變量值
三、異步ComletableFuture入門
- 分別是什么?然后如何使用?
總結
- 上一篇: 先天性心脏病可以通过产前诊断检测出来吗?
- 下一篇: 2999元起!vivo S10系列7月2