1. 程式人生 > >Java筆記--多執行緒

Java筆記--多執行緒

Java筆記–多執行緒

在講執行緒之前有必要討論一下程序的定義:程序是程式在一個數據集合上執行的過程,它是系統進行資源分配和排程的一個獨立單位。程序實體由程式段, 資料段 PCB(程序控制塊)組成。執行緒又是什麼?執行緒可以看做輕量級程序,執行緒是程序的執行單元,是程序排程的基本單位

還有一個概念就是併發性(concurrency)和並行性(parallel):並行是指在同一時刻,有多條指令在多個處理器上同時執行;併發指的是在同一時刻只能有一條指令執行,即每個指令以時間片為單位來執行
這裡寫圖片描述

1,執行緒的建立與啟動

Java使用Thread類代表執行緒,所有執行緒物件都是Thread類或其子類的例項

1.1,繼承Thread類來建立並啟動多執行緒

public class FirstThread extends Thread{

    private int i;

    @Override
    public void run() {
        for(i=0;i<100;i++) {
            //返回當前執行緒的名字
            System.out.println(getName()+" "+i);
        }
    }

    public static void main(String[] args) {


        for
(int i=0;i<100;i++) { //獲取當前執行緒 System.out.println(Thread.currentThread().getName()+" "+i); if(i==20) { //建立並啟動第一個執行緒 new FirstThread().start(); //建立並啟動第二個執行緒 new FirstThread().start(); /*FirstThread st1 = new FirstThread(); st1.start(); FirstThread st2 = new FirstThread(); st2.start();*/
} } } }

這裡寫圖片描述
繼承Thread類,重寫該類的run()方法,也就是這個執行緒需要完成的任務,執行緒物件的start()方法可以用來啟動該執行緒
使用繼承Thread類的方法來建立執行緒類時,多個執行緒之間無法共享執行緒類的例項變數

1.2,實現Runnable介面建立執行緒類

public class SecondThread implements Runnable{

    private int i;
    @Override
    public void run() {
        for(;i<100;i++) {

            //實現Runnable介面時,想獲取當前執行緒只能用Thread.currentThread
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }

    public static void main(String[] args) {
        for(int i=0;i<100;i++) {
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i==20) {
                SecondThread  st = new SecondThread();

                new Thread(st,"新程式設計1").start();
                new Thread(st,"新程式設計2").start();

                /*Thread t1 = new Thread(st,"新程式設計1");
                t1.start();
                Thread t2 = new Thread(st,"新程式設計2");
                t2.start();*/

            }
        }
    }
}

這裡寫圖片描述

實現Runnable介面,同樣的在run()方法中編寫需要執行緒實現的操作,採用執行緒物件的start()方法啟動,
使用實現Runnable介面的方法來建立執行緒類時,多個執行緒之間可以共享執行緒類的例項變數

1.3,實現Callable介面通過FutureTask包裝器來建立Thread執行緒

Callable介面提供了一個call()方法可以作為執行緒執行體,這個方法具有返回值,還可以宣告丟擲異常

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class ThirdThread {
    public static void main(String[] args) {
        //建立Callable物件
        ThirdThread rt = new ThirdThread();
        //先使用Lambda表示式建立Callable<Integer>物件
        //使用FutureTask來包裝Callable物件
        FutureTask<Integer> task = new FutureTask<>((Callable<Integer>)()->{
            int i=0;
            for(;i<100;i++) {
                System.out.println(Thread.currentThread().getName()+"迴圈變數i的值:"+i);
            }
            return i;
        });
        for(int i=0;i<100;i++) {
            System.out.println(Thread.currentThread().getName()+" 的迴圈變數i的值:"+i);
            if(i==20) {
                //實質還是以Callable物件來建立並啟動的
                new Thread(task,"有返回值的執行緒").start();

                /*Thread t = new Thread(task);
                t.start();*/
            }
        }
        try {
            System.out.println("子執行緒的返回值:"+task.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

這裡寫圖片描述

1.4,Runnable,Callable介面與Thread類的對比

採用實現Runnable,Callable介面優缺點:
1,介面可以多繼承,繼承了Runnable介面還能繼承其他介面
2,適合多個相同執行緒來處理同一份資源的情況,
3,缺點是,程式設計稍微複雜,訪問當前執行緒必須使用Thread.currentThread()
採用繼承Thread類優缺點:
1,編寫簡單,訪問當前執行緒可直接用this
2,缺點是,不能再繼承其他類
綜上,建議採用實現Runnable介面的方法來建立和啟動執行緒

1.5,synchronized關鍵字

synchronized關鍵字用於修飾方法和程式碼塊,以實現同步,當多個執行緒在執行被synchronized修飾的程式碼,以排隊的方式進行處理。當一個執行緒呼叫被修飾的程式碼時,先判斷有沒有被上鎖,如果上鎖就說明有其他執行緒在呼叫,必須等待其他執行緒結束呼叫後才能執行這段程式碼,synchronized可以在任意物件以及方法上加鎖,加鎖的這段程式碼被稱為“互斥區”或者“臨界區”
synchronized關鍵字加到static靜態方法是給Class類上鎖,而synchronized關鍵字加到非static靜態方法上是給物件上鎖

2,執行緒的生命週期

這裡寫圖片描述

線上程的生命週期中,要經過新建(new),就緒(Runnable),執行(Running),阻塞(Blocked)和死亡(Dead)5種狀態,CPU會在不同的執行緒之間來回切換,執行緒會不斷的經歷執行,阻塞

1,新建狀態:使用new關鍵字建立了一個執行緒,如Thread t = new MyThread();

2,就緒狀態:執行緒物件呼叫了start()方法後,執行緒進入就緒狀態,就緒狀態就是等待CPU的排程執行

3,執行狀態:CPU呼叫就緒狀態的執行緒,此時執行緒進入執行狀態

4,阻塞狀態:處於執行狀態中的執行緒由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才有機會再次被CPU呼叫以進入到執行狀態

5,死亡狀態:執行緒執行完畢或者異常退出,也可以用stop()方法來結束執行緒,但是容易造成死鎖

這些都是java多執行緒程式設計最基礎的東西,後面的等我看完《Java多執行緒程式設計核心技術》再來寫