如何創建線程?守護線程?阻塞線程?同步線程?

這篇文章主要是對線程有基本瞭解的夥伴當作筆記來瞅一眼。關於什麼是線程等問題不會進行描述。

一、創建線程

創建線程的方式主要有倆種,說是倆種,我們點進源碼去看一下,其實就是一種方式,因爲Thread類就是實現Runnable接口。換湯不換藥。

第一種:通過繼承Thread類重寫run方法:

public class CreateThread {
    public static void main(String[] args) {
        Thread t1 = new MyThread();
        //啓動線程
        t1.start();
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("創建線程!");
    }
}

簡寫方式:

//匿名內部類
new Thread(){
            @Override
            public void run() {
                System.out.println("創建線程!");
            }
        }.start();

第二種:通過實現Runnable接口重寫run方法:

public class createThread {
    public static void main(String[] args) {
        //實例化任務
        Runnable r1 = new MyRunnable();
        //創建線程同時指定任務
        Thread t1 = new Thread(r1);
        //等於Thread t1 = new Thread(new MyRunnable)
        t1.start();
    }
}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("創建線程!");
    }
}

簡寫方式:

new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("創建線程!");
            }
        }).start();

最簡方式 Lambda表達式:

new Thread(()-> System.out.println("創建線程!")).start();

二、阻塞線程

Thread類提供靜態方法sleep(),讓運行這個方法的線程阻塞指定毫秒。
注:這裏需要捕捉阻塞中斷異常!怎麼理解呢,就是在睡覺時醒來不是自然醒,被外力弄醒。

new Thread(()-> {
            try {
                //線程阻塞2秒
                Thread.sleep(2000);
                //2秒之後執行打印
                System.out.println("我自由了!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

有睡眠方法,肯定要有叫醒方法呀,也就是中斷線程阻塞。通過線程實例調用interrupt方法(會觸發異常),我這裏圖方便寫的匿名類,無法調用就不調用了。算了,貼一下代碼瞅一眼吧。

Thread t1 = new Thread(()->{
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();

        new Thread(()->{
            System.out.println("我要打斷t1線程睡眠!");
            t1.interrupt();
        }).start();

運行結果:
	我要打斷t1線程睡眠!
	java.lang.InterruptedException: sleep interrupted

三、守護線程

何爲守護線程?
守護線程又稱爲後臺線程,在默認情況下我們創建的線程都爲普通線程。在線程啓動之前調用setDaemon(true)方法纔會將普通線程變爲守護線程。
那麼守護線程與普通線程的區別是?
用我們的兵哥哥舉個例:我們這些普通的人民就是屬於普通線程,兵哥哥就是我們的守護線程。不管發生什麼危險與事故,永遠都是兵哥哥在我們的背後守護我們離開,待我們所有普通人民離開後,兵哥哥們纔會有序撤離。這樣應該就理解了:在普通線程全部結束後,所有正在運行的守護線程會被強制停止。進程就會結束。

Thread t1 = new Thread(()->{
            while(true){
                System.out.println("我是守護線程!");
            }
        });
        //在線程調用之前設置爲守護線程
        t1.setDaemon(true);
        t1.start();

        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                System.out.println("我是普通線程!");
            }
        }).start();

運行結果:
	我們在t1線程中寫的是一個死循環,運行之後會發現普通線程結束後
	我們的t1死循環線程也結束了!

四、同步線程

我們應該知道,線程屬於併發編程,每一個線程都是在埋頭各幹各的任務。如果我們有一個需求需要線程同步應該如何做?Thread類中提供join()方法(需要捕捉中斷異常)來協調多個線程同步。點開該方法看一下源碼註釋:Waits for this thread to die.意思很明顯了—>等待該線程死亡。
當然Thread類也重載了該join方法,可自行點開源碼查看。如 join(long millis)等待調用join方法的線程多少毫秒。
在這裏插入圖片描述

就舉一個我在班級中學過的一個例子:
我們打開一個網頁需要同時加載文字與圖片,在文字加載結束後,我們需要等待圖片加載完成才能將文字與圖片顯示出來。

Thread t1 = new Thread(()->{
            System.out.println("開始加載圖片!");

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("圖片加載完成!");
        });

        t1.start();

        new Thread(()->{
            System.out.println("開始加載文字!");
            System.out.println("文字加載完成!");

            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("全部加載成功,開始顯示網頁!");

        }).start();

運行結果:
在這裏插入圖片描述

:在使用線程的時候一定需要注意線程安全的問題!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章