首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 多線程入門核心:實現方式、生命週期、同步機制與線程通信全解析

     編輯:Java 綜合教學

Java 多線程入門核心:實現方式、生命週期、同步機制與線程通信全解析

多線程是 Java 並發編程的基石。本文系統梳理線程創建、狀態流轉、常用方法、同步鎖、Lock 機制、死鎖條件與管道流通信,附完整代碼範例,助你建立扎實的並發基礎。

一、實現多線程的兩種核心方式

1. 實現 Runnable 接口(推薦)

public class MyRunnable implements Runnable {
    private final String name;
    public MyRunnable(String name) { this.name = name; }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " 第 " + i + " 次運行");
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
        }
        System.out.println(name + " 運行完畢停機");
    }
}

// 測試啟動
public class Test {
    public static void main(String[] args) {
        new Thread(new MyRunnable("0號機")).start();
        new Thread(new MyRunnable("1號機")).start();
    }
}

優勢:避免單繼承限制,便於共享同一任務實例,適合資源共享場景。

2. 繼承 Thread 類

public class MyThread extends Thread {
    private final String name;
    public MyThread(String name) { this.name = name; }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " 第 " + i + " 次運行");
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
        }
        System.out.println(name + " 運行完畢停機");
    }
}

// 測試啟動
public class Test {
    public static void main(String[] args) {
        new MyThread("0號機").start();
        new MyThread("1號機").start();
    }
}

缺點:佔用繼承名額,每個線程需獨立實例,不利於任務與線程分離。

二、線程五大狀態與流轉

狀態觸發條件說明
初始 (NEW)new Thread()線程對象創建,未調用 start()
就緒 (RUNNABLE)start()進入線程隊列,等待 CPU 調度
運行 (RUNNING)獲得 CPUrun() 正在執行
阻塞 (BLOCKED)sleep()/wait()/I/O/同步鎖暫時放棄 CPU,釋放或持有鎖視具體方法而定
死亡 (TERMINATED)run() 結束 / stop() / 異常線程生命週期結束
關鍵區別:sleep() 不釋放鎖,佔用 CPU(計時);wait() 釋放鎖,不佔用 CPU,需配合 notify()/notifyAll() 喚醒。

三、線程常用方法速查表

方法作用備註
start()啟動線程,由 JVM 調用 run()不可直接調用 run(),否則變單線程
sleep(ms)當前線程休眠指定毫秒靜態方法,不釋放鎖
yield()當前線程讓出 CPU,重新競爭不保證調度結果
join()當前線程等待目標線程結束常用於主線程等待子線程
interrupt()中斷線程(設置中斷標誌)需配合 isInterrupted() 或捕獲 InterruptedException
setPriority(int)設置優先級 1-10建議用 MAX/MIN/NORM_PRIORITY 常量,跨平台可移植
setDaemon(true)標記為守護線程JVM 僅剩守護線程時自動退出
wait()/notify()/notifyAll()Object 監視器方法,需在 synchronized 內調用實現線程協作核心

四、同步機制:synchronized vs Lock

1. synchronized 關鍵字

  • 修飾實例方法:鎖為 this,同一實例的所有 synchronized 方法互斥。
  • 修飾靜態方法:鎖為 ClassName.class(類鎖),全類互斥。
  • 修飾代碼塊:synchronized(obj) { ... },可精確控制鎖範圍與鎖對象。
每個實例擁有唯一對象鎖,類擁有唯一類鎖,兩者互不干擾。同一線程可同時持有對象鎖與類鎖(可重入)。

2. Lock 介面(java.util.concurrent.locks)

Lock lock = new ReentrantLock();
try {
    lock.lock();           // 獲取鎖,阻塞直到成功
    // 臨界區代碼
    return result;         // return 必須在 try 內,確保 finally 執行
} finally {
    lock.unlock();         // 釋放鎖,防止死鎖
}
特性synchronizedLock
鎖獲取失敗無限等待tryLock() 可立即返回/超時返回
公平性非公平可構建公平鎖 new ReentrantLock(true)
條件變量wait/notifynewCondition() 支援多條件隊列
性能低競爭優,高競爭劣高競爭下穩定

五、死鎖四必要條件與預防

  1. 互斥條件:資源不可共享(鎖天然滿足)。
  2. 不可搶佔:持有者主動釋放(鎖天然滿足)。
  3. 請求保持:持有資源又請求新資源 → 破壞:一次性申請所有資源。
  4. 循環等待:形成環狀鏈 → 破壞:按固定順序獲取鎖。

Java 中只能人為避免條件 3、4,編碼時遵循「鎖排序法」與「嘗試性獲取鎖(tryLock)」。

六、管道流實現線程間通信

管道流提供單向通道,成對使用:

  • 字節流:PipedInputStream / PipedOutputStream
  • 字符流:PipedReader / PipedWriter
// 創建與連接
PipedWriter writer = new PipedWriter();
PipedReader reader = new PipedReader(writer);  // 或 writer.connect(reader)

// 生產者線程
new Thread(() -> {
    while (true) {
        writer.write("番茄,這裡是西紅柿,收到請回答\n");
        writer.flush();
        Thread.sleep(2000);
    }
}).start();

// 消費者線程
new Thread(() -> {
    int ch;
    while ((ch = reader.read()) != -1) System.out.print((char) ch);
}).start();
注意:讀寫線程均不得退出或長時間阻塞,否則拋出 IOException: Write/Read end dead。

參考資料:《Java 編程思想》第 4 版、JDK 7 在線 API 文檔。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved