一、多線程概念
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();
}
}