java學習筆記——多線程基礎

創建新線程

繼承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要立刻更新內存中的信息

參考資料

多線程 - 廖雪峯的官方網站

深入淺出Java多線程

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