聊聊執行緒(一)執行緒的基礎
阿新 • • 發佈:2020-12-17
執行緒基礎
程序和執行緒
- 程序:正在執行的程式,需要記憶體和CPU資源進行運算執行,
一個程式包含一個或多個程序 - 執行緒:是程序的組成單元,一個程序包含一個或多個執行緒,每個執行緒負責單獨執行一個任務
- 程序和執行緒的區別:
- 一個程序包含一個或多個執行緒
- 每個程序都有自己獨立的記憶體空間,執行緒沒有自己獨立的記憶體空間,執行緒共享所在程序的記憶體空間
- 程序是重量級的單元,需要系統資源比較多,執行緒是輕量級單元,需要資源比較少
多程序和多執行緒
- 多程序是作業系統可以同時執行多個程序。一個CPU核心一個時間只能執行一個程序,CPU會在多個程序之間進行來回切換,因為速度特別快,使用者感覺不到。
- 多執行緒是一個程序裡面有多個執行緒,CPU執行程序時會來回切換裡面所有的執行緒,每個執行緒會分配到一定的CPU的執行時間(CPU時間片)
多執行緒的應用場景
- JAVAEE企業級開發:大量的使用者需要同時訪問網站的伺服器,如:雙十一、秒殺等。如果伺服器只有一個執行緒,多個使用者需要排隊和伺服器通訊,效率非常低;多執行緒就是一個使用者連線伺服器後,伺服器就會開一個新執行緒負責使用者的通訊,使用者之間就不會相互影響。
- 遊戲開發:同時進行網路通訊、遊戲角色控制、圖形繪製等操作,必須每個用一個執行緒執行。
並行和併發
- 併發:一個CPU在多個執行緒之間快速切換,達到同時執行多個任務的目的
- 並行:多個CPU可以同時執行一個程序中的多個執行緒
執行緒的實現
1、 繼承Thread類
- 繼承Thread類
- 重寫run方法
- 建立執行緒物件,呼叫start方法
/** * 自定義執行緒類 * @author xray * */ public class MyThread extends Thread{ /** * 執行執行緒任務的方法 */ public void run(){ //Thread.currentThread()是獲得系統當前執行的執行緒 System.out.println(Thread.currentThread().getName()+"執行緒執行了!!!"); } public static void main(String[] args) { //主執行緒中執行 System.out.println(Thread.currentThread().getName()+"執行緒執行了!!!"); //建立執行緒物件 MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); //啟動執行緒 thread1.start(); thread2.start(); } }
2、實現Runnable介面
- 實現Runnable介面
- 實現run方法
- 建立自定義執行緒物件,作為引數傳入Thread物件
- 呼叫start方法
/**
* 自定義執行緒類
* @author xray
*
*/
public class MyRunnable implements Runnable{
/**
* 實現run方法
*/
@Override
public void run() {
System.out.println("當前執行的執行緒是:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
//建立Thread物件,傳入Runnable物件
Thread thread1 = new Thread(new MyRunnable());
//呼叫start方法
thread1.start();
//使用匿名內部類實現Runnable
Thread thread2 = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("匿名內部類,當前執行的執行緒是:"+Thread.currentThread().getName());
}
});
thread2.start();
//使用Lambda實現Runnable
Thread thread3 = new Thread(()->{
System.out.println("Lambda,當前執行的執行緒是:"+Thread.currentThread().getName());
});
thread3.start();
}
}
3、實現Callable介面
前面兩種方法都不能返回結果,Callable的方法可以返回值
- 實現Callable介面,實現call方法
- 建立FutureTask物件,傳入Callable物件
- 建立Thread物件,傳入FutureTask物件
- 呼叫Thread物件的start方法
- 呼叫FutureTask物件的get方法,獲得返回值
/**
* Callable的實現類
* @author xray
*
*/
public class MyCallable implements Callable<Long>{
@Override
public Long call() throws Exception {
System.out.println("執行call的執行緒是:"+Thread.currentThread().getName());
//模擬執行耗時運算
Long sum = 0L;
for(int i = 0;i < 100000000L;i++){
sum += i;
}
//返回結果
return sum;
}
public static void main(String[] args) {
//建立FutureTask物件,傳入Callable物件
FutureTask<Long> task = new FutureTask<>(new MyCallable());
//建立Thread,傳入FutureTask物件
Thread thread = new Thread(task);
//啟動執行緒
thread.start();
//獲得結果
try {
// long result = task.get();
long result = task.get(5,TimeUnit.SECONDS);
System.out.println("獲得計算結果:"+result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
執行緒的生命週期
- 新建
執行緒new出來,沒有呼叫start方法,CPU沒有分配時間片 - 就緒
執行緒呼叫了start方法,CPU準備分配時間片,但是沒有真正分配 - 執行
執行緒搶到了CPU,開始執行run方法 - 阻塞
進入阻塞狀態:- 呼叫sleep方法
- 執行緒的鎖呼叫wait方法
- 呼叫suspend(掛起)方法
- 流的IO操作
從阻塞恢復: - sleep的時間完畢
- 鎖呼叫notify或notifyAll方法
- 呼叫resume(恢復)方法
- IO操作完畢
阻塞狀態結束後,回到就緒狀態
- 死亡,run方法執行完畢後執行緒進入死亡狀態