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

Java多線程編程基礎(一):線程對象與線程的本質區別

     編輯:Java 相關知識

前言:多線程是現代計算的核心模型

隨著CPU主頻觸頂(~4GHz)、多核成主流,多線程並行編程成為發揮硬件性能的唯一路徑。Java作為內置線程支持的主流語言,掌握其線程模型是高性能開發的必修課。本系列從最基礎概念切入,層層遞進構建完整知識體系。

一、 核心概念辨析:線程對象 ≠ 線程

概念本質創建方式生命周期屬於
線程對象Java堆上普通對象(Thread/Runnable實例)new Thread()、new MyRunnable()GC回收前存活Java語言層
線程OS內核調度實體,擁有PC寄存器、棧、上下文thread.start() → JNI調用pthread_create/CreateThreadrun()結束/異常終止OS/硬件層

關鍵洞見:new Thread()僅創建Java對象,**不啟動OS線程**;start()才請求OS創建真實線程,並安排執行run()。對象可重用,線程一次性(start()只能調用一次)。

二、 單線程基線:main線程


public class SingleThread {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println("Hello, World!");
        }
    }
}

啟動流程:

  1. JVM進程啟動(由啟動器java創建)
  2. 主線程(Main Thread)由JVM內部創建,非Thread.start()產生
  3. 主線程執行main()入口
  4. main()返回 → 主線程結束 → JVM進程退出(非守護線程全結束)

此過程僅一條用戶線程(主線程),稱為單線程模型。JVM後台仍有GC、JIT、Finalizer等守護線程,但不可訪問。

三、 邁入多線程:第一個子線程


class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread say: Hello, World!");
    }
}

public class MultiThread {
    public static void main(String[] args) {
        new MyThread();           // ① 僅創建線程對象,無線程啟動
        new MyThread().start();   // ② 創建對象 + 啟動線程
        System.out.println("Main say: Hello, World"); // ③ 主線程繼續執行
    }
}

可能輸出順序(單核時間片輪轉):


Main say: Hello, World
Thread say: Hello, World!

或相反。調度非確定性是多線程核心特徵。

四、 並發 vs 並行:概念精準定義

  • 並發:單CPU,多線程交替執行,微觀串行、宏觀並行。時間片輪轉、協作式調度
  • 並行:多CPU/多核,多線程物理同時執行,真正同時刻

JavaThread統一抽象兩者,代碼無差別。JVM將Java線程1:1映射到OS內核線程(現代Linux/Windows/macOS),由OS調度器決定並發/並行。

五、 線程對象創建兩大路徑

路徑1:繼承Thread類


class MyThread extends Thread {
    @Override public void run() { ... }
}
Thread t = new MyThread();
t.start();

缺點:繼承佔用單繼承名額、線程對象與任務耦合、一個對象只能start()一次。

路徑2:實現Runnable接口(推薦)


class MyTask implements Runnable {
    @Override public void run() { ... }
}
Runnable task = new MyTask();
new Thread(task).start(); // 可創建多個Thread包裝同一Runnable
new Thread(task).start(); // 多線程共享同一任務實例

優勢:任務與線程分離、支持線程池、可共享狀態、函數式編程友好(Lambda() -> {})。

六、 線程基本操作速查

操作方法說明
啟動start()請求OS創建線程,異步返回,run()在新線程執行
等待終止join() / join(millis)當前線程阻塞,直到目標線程結束
睡眠Thread.sleep(millis)當前線程讓出CPU,不釋放鎖
讓步Thread.yield()暗示調度器重新調度,不保證
中斷interrupt() / isInterrupted() / interrupted()協作式中斷機制,不強制停止
守護線程setDaemon(true)JVM僅剩守護線程時退出,需在start()前設置
優先級setPriority(1-10)提示調度器,平台相關性強,慎用
獲取當前Thread.currentThread()返回正在執行代碼的Thread對象

七、 實戰驗證:join()控制執行順序


public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Child: " + i);
                try { Thread.sleep(100); } catch (InterruptedException e) { break; }
            }
        });
        t.start();
        t.join(); // 主線程等待t結束
        System.out.println("Main: child finished");
    }
}

輸出:Child 0-4 全部打印後,才打印Main。join()實現線程順序協調。

八、 總結與下一站預告

本文確立三大基石:

  1. 線程對象 ≠ 線程 — 對象可重用、線程一次性
  2. start() ≠ run() — start()啟動新線程,run()只是普通方法調用
  3. Runnable > Thread — 任務與線程解耦,支撐線程池、函數式編程

下一站:線程對象核心方法深度解析 — join()、sleep()、interrupt()、yield()、守護線程、線程組、ThreadLocal原理與內存洩漏。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved