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

Java 多執行緒:建立兩個執行緒與主執行緒交替執行

     編輯:關於C

程式碼架構

class E implements Runnable {
    public void run() {
        for (int x = 0; x < 10; x++) {
            System.out.println(Thread.currentThread().getName() + "我是:" + x);
        }
    }
}

public class Threade_15 {
    public static void main(String[] args) {
        E ee = new E();
        Thread t1 = new Thread(ee);
        Thread t2 = new Thread(ee);
        t1.start();
        t2.start();
        
        for (int x = 0; x < 10; x++) {
            System.out.println(Thread.currentThread().getName() + "我是:" + x);
        }
    }
}

執行流程解析

  1. main 執行緒啟動
  2. 建立 Runnable 實作物件 ee
  3. 建立兩個 Thread 物件 t1、t2,共用同一 ee
  4. 呼叫 t1.start()、t2.start() 啟動執行緒(非同步)
  5. main 執行緒繼續執行自己的迴圈
  6. 三個執行緒(main, t1, t2)並發執行,由 CPU 排程器決定切換時機

關鍵概念說明

Runnable vs Thread 繼承

start() vs run()

  • start():啟動新執行緒,JVM 呼叫 run(),**非阻塞**
  • run():直接在當前執行緒呼叫,**阻塞**直到結束
  • ❌ 錯誤:`t1.run()` — 不會建立新執行緒

共用 Runnable 實例的效果

t1 和 t2 共用同一個 E 實例 ee,意味著:

  • 若 E 有實例變數,兩執行緒會共享(需同步)
  • 本例中 run() 只有區域變數 x,無共享資料競爭

輸出特性:非確定性順序

可能的輸出片段:
main我是:0
Thread-0我是:0
Thread-1我是:0
main我是:1
Thread-0我是:1
...

三個執行緒輸出交錯順序不固定,取決於:

  • 作業系統排程器
  • CPU 核心數
  • 系統負載
  • JVM 執行緒實作

「交替執行」的誤區與實現

標題提到「交替運行」,但程式碼並未強制交替。真正的交替需同步機制:

方案一:使用 wait/notify

class AlternatingTask implements Runnable {
    private final Object lock = new Object();
    private int turn = 0;  // 0=main, 1=t1, 2=t2
    private final int myTurn;
    
    public AlternatingTask(int myTurn) { this.myTurn = myTurn; }
    
    public void run() {
        for (int i = 0; i < 10; i++) {
            synchronized (lock) {
                while (turn != myTurn) {
                    try { lock.wait(); } catch (InterruptedException e) {}
                }
                System.out.println(Thread.currentThread().getName() + ":" + i);
                turn = (turn + 1) % 3;
                lock.notifyAll();
            }
        }
    }
}

方案二:使用 Semaphore(信號量)

Semaphore sMain = new Semaphore(1);
Semaphore sT1 = new Semaphore(0);
Semaphore sT2 = new Semaphore(0);

// 各執行緒:acquire 自己的 semaphore,執行完 release 下一個
// main: sMain.acquire() -> print -> sT1.release()
// t1:   sT1.acquire()   -> print -> sT2.release()
// t2:   sT2.acquire()   -> print -> sMain.release()

最佳實踐總結

  1. 優先使用 Runnable 介面而非繼承 Thread
  2. 共享資料時必須同步(synchronized, Lock, volatile, Atomic*)
  3. 執行緒間協調使用高層建構(CountDownLatch, CyclicBarrier, Phaser, Semaphore)
  4. 避免直接操作執行緒狀態(stop(), suspend(), resume() 已棄用)
  5. 使用執行緒池(ExecutorService)管理生命週期

本例展示了最基礎的多執行緒建立方式,理解「並發非決定性」是進階多執行緒編程的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方式實作 Runnable繼承 Thread
靈活度高(可繼承其他類別)低(單繼承限制)
資源共享自然支援(同一 Runnable 實例)需額外設計
關注點分離任務邏輯與執行緒控制分離混合在一起