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

Java 線程兩種創建方式與交替執行實戰:Runnable vs Thread、wait/notify 同步控制詳解

     編輯:Java 綜合教學

Java 線程兩種創建方式與交替執行實戰:Runnable vs Thread、wait/notify 同步控制詳解

線程是 Java 併發編程基石。本文梳理兩種創建方式,並通過「兩線程交替打印時間」案例講解 wait/notify 同步機制。

方式一:繼承 Thread 類

public class ThreadOne extends Thread {
    @Override public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(this.getName() + ":" + i);
        }
    }
    public static void main(String[] args) {
        new ThreadOne().start(); // 必須調用 start(),非 run()
    }
}

方式二:實現 Runnable 介面(推薦)

public class MyThread implements Runnable {
    @Override public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "放入一個蘋果:" + i);
            try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); }
        }
    }
    public static void main(String[] args) {
        MyThread task = new MyThread();
        new Thread(task).start(); // 同一任務可被多線程共享
    }
}

核心差異

  • 繼承 Thread:簡單,但單繼承限制,任務與線程耦合
  • 實現 Runnable:解耦任務與執行,支援線程池、Lambda、多線程共享任務實例

案例:兩線程交替打印時間(每秒一次,各 5 次)

預期輸出

Thread-0 Sun Feb 28 11:21:52 CST 2016
Thread-1 Sun Feb 28 11:21:53 CST 2016
Thread-0 Sun Feb 28 11:21:54 CST 2016
Thread-1 Sun Feb 28 11:21:55 CST 2016
... 共 10 行

同步控制邏輯

  • 共享鎖對象 Object lock = new Object()
  • 狀態變量 int state = 1(1=線程A執行, 2=線程B執行)
  • 計數器 countA、countB 控制各 5 次
  • 執行流程:獲取鎖 → 判斷 state → 不符合 wait() → 執行業務 → 修改 state → notifyAll() → 釋放鎖

完整代碼

public class ThreadDate {
    private static int state = 1;
    private static int countA = 0, countB = 0;
    private static final Object LOCK = new Object();

    public static void main(String[] args) {
        // 線程 A
        new Thread(() -> {
            while (countA < 5) {
                synchronized (LOCK) {
                    while (state != 1) { try { LOCK.wait(); } catch (InterruptedException e) {} }
                    System.out.println(Thread.currentThread().getName() + " " + new Date());
                    try { Thread.sleep(1000); } catch (InterruptedException e) {}
                    state = 2;
                    LOCK.notifyAll();
                }
                countA++;
            }
        }).start();

        // 線程 B
        new Thread(() -> {
            while (countB < 5) {
                synchronized (LOCK) {
                    while (state != 2) { try { LOCK.wait(); } catch (InterruptedException e) {} }
                    System.out.println(Thread.currentThread().getName() + " " + new Date());
                    try { Thread.sleep(1000); } catch (InterruptedException e) {}
                    state = 1;
                    LOCK.notifyAll();
                }
                countB++;
            }
        }).start();
    }
}

關鍵點總結

  1. wait()/notify() 必須在 synchronized 區塊內調用,否則拋 IllegalMonitorStateException
  2. 使用 while 而非 if 判斷條件,防止虛假喚醒
  3. notifyAll() 喚醒所有等待線程,配合狀態變量讓目標線程繼續
  4. 現代替代方案:BlockingQueue、CountDownLatch、CyclicBarrier、Phaser 更簡潔安全
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved