首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 多線程陷阱:直接呼叫 run() 不會開啟新線程,輸出必為 12

     編輯:程式設計疑難解答

代碼分析

public class Demo {
    private static int i = 10;
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                i++;
                i++;
            }
        }).run(); // 錯誤:直接呼叫 run()
        System.out.println(i);
    }
}

關鍵點

  • Thread.start():啟動新線程,由 JVM 排程執行 run()。
  • Thread.run():單純方法呼叫,在當前主線程中同步執行,不會開啟新線程。

執行流程

  1. 主線程執行至 new Thread(...).run()。
  2. 當前線程(主線程)直接進入 run() 方法體。
  3. 執行 i++ 兩次,i 從 10 變為 12。
  4. run() 返回,繼續執行 System.out.println(i),輸出 12。

正確寫法

new Thread(() -> {
    i++;
    i++;
}).start(); // 必須呼叫 start()

// 若需等待子線程結束再輸出
Thread t = new Thread(() -> { i++; i++; });
t.start();
t.join(); // 主線程阻塞等待
System.out.println(i); // 此時才能保証看到 12(但順序已無意義)

補充:線程安全隱患

即使改用 start(),i++ 非原子操作(讀取-修改-寫入),多線程並發會導致資料競爭。解決方案:

  • AtomicInteger:AtomicInteger i = new AtomicInteger(10); i.incrementAndGet();
  • synchronized 關鍵字鎖定關鍵區段。
  • volatile 僅保證可見性,不保證原子性,不適用於 i++。

總結

run() 是普通方法,start() 才是開啟線程的鑰匙。初學者最易混淆的「以為呼叫 run 就能多線程」,請牢記:**新線程從 start() 開始,而非 run()**。

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