天天看點

認真閱讀完這篇文章熟練掌握多線程相關基礎知識

一、多線程概念

1、什麼是程式?一個程式可以有多個程序

程式是一段靜态的代碼,它是應用程式執行的藍本

2、什麼是程序?一個程序可以有多個線程

程序是一種正在運作的程式,有自己的位址空間。

作為藍本的程式可以被多次加載到系統的不同記憶體區域分别執行,形成不同的程序。

基于程序的特點是允許計算機同時運作兩個或更多的程式。

3、什麼是線程?

線程是程序内部單一的一個順序控制流。一個程序在執行過程中,可以産生多個線程,每個線程也有自己産生,存在和消亡的過程。

4、什麼是并發?

并發當有多個線程在操作時,如果系統隻有一個CPU,則它根本不可能真正同時進行一個以上的線程,它隻 能把CPU運作時間劃分成若幹個時間段,再将時間 段配置設定給各個線程執行,在一個時間段的線程代碼運作 時,其它線程處于挂起狀。.這種方式我們稱之為并發(Concurrent)。

5、什麼是并行?

當系統有一個以上CPU時,則線程的操作有可能非并發。當一個CPU執行一個線程時,另一個CPU可 以執行另一個線程,兩個線程互不搶占CPU資源,可以同時進行,這種方式我們稱之為并行 (Parallel)。

6、并發與并行的差別

并發和并行是即相似又有差別的兩個概念,并行是指兩個或者多個事件在同一時刻發生;而并發是 指兩個或多個事件在同一時間間隔内發生。在多道程式環境下,并發性是指在一段時間内宏觀上有多個程 序在同時運作,但在單處理機系統中,每一時刻卻僅能有一道程式執行,故微觀上這些程式隻能是分時地 交替執行。倘若在計算機系統中有多個處理機,則這些可以并發執行的程式便可被配置設定到多個處理機上, 實作并行執行,即利用每個處理機來處理一個可并發執行的程式,這樣,多個程式便可以同時執行。

二、實作多線程類方法

1、Runnable接口

public class Th1 implements Runnable {
    public void run() {
        System.out.println("th1");
    }
}      

2、繼承Thread類

public class Th2 extends Thread {
    public void run() {
        System.out.println("th2");
    }
}      

3、Callable 接口

public class Th3 implements Callable<Integer> {
    public Integer call() {
        System.out.println("call");
        return 300;
    }

}      

test類:

package duoxiancheng;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author yeqv
 * @program A2
 * @Classname test
 * @Date 2022/1/27 22:33
 * @Email [email protected]
 */
public class test {
    public static void main(String[] args) {
        //執行個體化Th3
        Th3 th3 = new Th3();
        // 執行 Callable 方式,需要 FutureTask 實作類的支援
        // FutureTask 實作類用于接收運算結果, FutureTask 是 Future 接口的實作類
        FutureTask<Integer> result = new FutureTask<>(th3);
        //開啟線程
        new Thread(result).start();
        try {
            //當線程執行完成後傳回結果列印出來
            System.out.println(result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}      

4、綜合線程實作

package duoxiancheng;

/**
 * @author yeqv
 * @program A2
 * @Classname Test1
 * @Date 2022/1/27 22:59
 * @Email [email protected]
 */
public class Test1 {
    public static void main(String[] args) {
        //建立方法一 實作Runnable接口,并作為Thread類參數
        //lambda表達式建立多線程并開啟
        new Thread(() -> {
            System.out.println("t1");
        }).start();
        //建立新的多線程對象,參數是之前定義過的一個多線程類對象
        Thread t2 = new Thread(new Th1());
        //啟動新多線程對象
        t2.start();
        //建立方法二 繼承Thread 類,重寫run方法
        var t3 = new Th2();
        //改線程名字
        t3.setName("線程三");
        //列印線程名
        System.out.println(t3.getName());
        //開啟線程
        t3.start();

    }
}      
package duoxiancheng;

import java.util.concurrent.TimeUnit;

/**
 * @author yeqv
 * @program A2
 * @Classname Test2
 * @Date 2022/1/27 23:20
 * @Email [email protected]
 */
public class Test2 {
    public static void main(String[] args) {
        //多線程 方法一 繼承Thread
        var t1 = new Thread() {
            @Override
            public void run() {
                this.setName("one thread");
                System.out.println(this.getName());
            }
        };
        t1.setName("one1111 thread");
        System.out.println(t1.getName());
        t1.start();
        //多線程 方法二 實作接口,實作Thread作為參數
        var t2 = new Runnable() {
            public void run() {
                String n = Thread.currentThread().getName();
                System.out.println(n);
            }
        };
        var t22 = new Thread(t2, "two thread");
        t22.setName("two2222 thread");
        t22.start();
        //main線程輸出
        try {
            TimeUnit.SECONDS.sleep(2);
            Thread.currentThread().setName("main thread");
            System.out.println(Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}      

三、多線程狀态及常用方法

認真閱讀完這篇文章熟練掌握多線程相關基礎知識

JAVA線程具有的五種基本狀态:

1、建立狀态(New):

當線程對象對建立後,即進入了建立狀态,如:Thread t = new MyThread();

2、就緒狀态(Runnable):

當調用線程對象的start()方法(t.start();),線程即進入就緒狀态。處于就緒狀态的線程,隻是說明此線程已經做好了準備,随時等待CPU排程執行,并不是說執行了t.start()此線程立即就會執行;

3、運作狀态(Running):

當CPU開始排程處于就緒狀态的線程時,此時線程才得以真正執行,即進入到運作狀态。注:就 緒狀态是進入到運作狀态的唯一入口,也就是說,線程要想進入運作狀态執行,首先必須處于就緒狀态中;

4、阻塞狀态(Blocked):

處于運作狀态中的線程由于某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀态,直到其進入到就緒狀态,才 有機會再次被CPU調用以進入到運作狀态。根據阻塞産生的原因不同,阻塞狀态又可以分為三種:

1,等待阻塞:運作狀态中的線程執行wait()方法,使本線程進入到等待阻塞狀态;

2,同步阻塞 : 線程在擷取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀态;

3,其他阻塞 : 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀态。當sleep()狀态逾時、join()等待線程終止或者逾時、或者I/O處理完畢時,線程重新轉入就緒狀态。

5、死亡狀态(Dead):

線程執行完了或者因異常退出了run()方法,該線程結束生命周期。

package duoxiancheng;

/**
 * @author yeqv
 * @program A2
 * @Classname Test3
 * @Date 2022/1/27 23:40
 * @Email [email protected]
 */
public class Test3 {
    public static void main(String[] args) {
        //建立線程
        var t = new Thread(() -> {
            System.out.println("ttttt");
        });
        //更改線程優先級
        t.setPriority(Thread.MAX_PRIORITY);
        //啟動線程
        t.start();
    }
}