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