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

Java 多線程基礎:線程創建與啟動詳解

     編輯:Java 相關知識

Java 內置多線程支持,所有實現 Runnable 接口的類實例均可作為線程任務。本文系統講解線程創建的兩種標準方式、start() 與 run() 的本質區別、線程生命週期及常見誤區。

核心概念

  • Thread 類實現了 Runnable,代表一個線程實例
  • 啟動線程唯一途徑:調用 Thread.start() 實例方法
  • start() 是 native 方法,會請求 JVM 創建新線程並異步執行 run()
  • 直接調用 run() 只是普通方法調用,不會創建新線程
  • 線程執行結束後 不能重啟,需新建實例再次 start()

方式一:繼承 Thread 類

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread.run() 執行於線程:" + Thread.currentThread().getName());
    }
}

// 啟動
new MyThread().start();

優點:代碼簡潔,直接訪問 this 即當前線程對象。
缺點:Java 單繼承限制,若已繼承其他類則無法使用。

方式二:實現 Runnable 接口(推薦)

public class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println("MyTask.run() 執行於線程:" + Thread.currentThread().getName());
    }
}

// 啟動
MyTask task = new MyTask();
Thread thread = new Thread(task);
thread.start();

優點:

  • 任務與線程控制分離,符合「組合優於繼承」原則
  • 同一 Runnable 實例可提交給多個線程(如線程池)
  • 便於實現資源共享(多線程操作同一任務對象字段)
  • 支持 Lambda 表達式(Java 8+):new Thread(() -> System.out.println("Hi")).start();

關鍵對比:start() vs run()

調用方式線程創建執行線程是否異步
thread.start()是新線程是
thread.run()否當前線程否(同步阻塞)

線程生命週期狀態

NEW → RUNNABLE → RUNNING → BLOCKED/WAITING/TIMED_WAITING → TERMINATED
  • NEW:new Thread() 創建,未調用 start()
  • RUNNABLE:調用 start() 後,等待 CPU 調度
  • RUNNING:獲得 CPU 正在執行 run()
  • BLOCKED:等待監視器鎖(synchronized)
  • WAITING:無限期等待(Object.wait()、Thread.join())
  • TIMED_WAITING:限時等待(sleep()、wait(timeout)、join(timeout))
  • TERMINATED:run() 正常返回或拋出未捕獲異常結束

常見誤區與最佳實踐

  • ❌ new Thread(new MyTask()).run() — 忘記 start(),主線程同步執行任務
  • ❌ 線程對象重複 start() — 拋出 IllegalThreadStateException
  • ✅ 使用線程池(ExecutorService)管理線程生命週期,避免頻繁創建銷毀開銷
  • ✅ 任務類實現 Runnable 或 Callable,與執行策略解耦
  • ✅ 守護線程(setDaemon(true))用於後台輔助任務,JVM 退出時不等待其結束

完整示例:帶異常處理的任務提交

public class SafeTask implements Runnable {
    private final String taskName;
    
    public SafeTask(String taskName) { this.taskName = taskName; }
    
    @Override
    public void run() {
        try {
            System.out.println("[" + taskName + "] 開始執行");
            // 業務邏輯...
            Thread.sleep(1000);
            System.out.println("[" + taskName + "] 正常結束");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 保持中斷狀態
            System.out.println("[" + taskName + "] 被中斷");
        } catch (Exception e) {
            System.err.println("[" + taskName + "] 異常:" + e.getMessage());
        }
    }
}

// 使用線程池執行
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new SafeTask("Task-1"));
executor.submit(new SafeTask("Task-2"));
executor.shutdown();

掌握線程創建啟動本質,是編寫正確並發程序的起點。實際開發中強烈建議使用線程池與 Runnable/Callable 任務模式,而非手動管理 Thread 實例。

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