1. 程式人生 > >java多執行緒程式設計之連續列印abc的幾種解法

java多執行緒程式設計之連續列印abc的幾種解法

java多執行緒程式設計之連續列印abc的解法

一道程式設計題如下:

例項化三個執行緒,一個執行緒列印a,一個執行緒列印b,一個執行緒列印c,三個執行緒同時執行,要求打印出10個連著的abc。

題目分析:

通過題意我們可以得出,本題需要我們使用三個執行緒,三個執行緒分別會列印6次字元,關鍵是如何保證順序一定是abc…呢。所以此題需要同步機制來解決問題!

令列印字元A的執行緒為ThreadA,列印B的ThreadB,列印C的為ThreadC。問題為三執行緒間的同步喚醒操作,主要的目的就是使程式按ThreadA->ThreadB->ThreadC->ThreadA迴圈執行三個執行緒,因此本人整理出了三種方式來解決此問題。


通過兩個鎖(不推薦,可讀性和安全性比較差)
package com.demo.test;

/**
* 基於兩個lock實現連續列印abcabc….
* @author GiggleXiang
*
*/
public class TwoLockPrinter implements Runnable {

// 列印次數
private static final int PRINT_COUNT = 10;
// 前一個執行緒的列印鎖
private final Object fontLock;
// 本執行緒的列印鎖
private final Object thisLock;
// 列印字元
private final char printChar;

public TwoLockPrinter(Object fontLock, Object thisLock, char printChar) {
    this.fontLock = fontLock;
    this.thisLock = thisLock;
    this.printChar = printChar;
}

@Override
public void run() {
    // 連續列印PRINT_COUNT次
    for (int i = 0; i < PRINT_COUNT; i++) {
        // 獲取前一個執行緒的列印鎖
        synchronized (fontLock) {
            // 獲取本執行緒的列印鎖
            synchronized (thisLock) {
                //列印字元
                System.out.print(printChar);
                // 通過本執行緒的列印鎖喚醒後面的執行緒 
                // notify和notifyall均可,因為同一時刻只有一個執行緒在等待
                thisLock.notify();
            }
            // 不是最後一次則通過fontLock等待被喚醒
            // 必須要加判斷,不然雖然能夠列印10次,但10次後就會直接死鎖
            if(i < PRINT_COUNT - 1){
                try {
                    // 通過fontLock等待被喚醒
                    fontLock.wait();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }    
    }    
}

public static void main(String[] args) throws InterruptedException {
    // 列印A執行緒的鎖
    Object lockA = new Object();
    // 列印B執行緒的鎖
    Object lockB = new Object();
    // 列印C執行緒的鎖
    Object lockC = new Object();

    // 列印a的執行緒
    Thread threadA = new Thread(new TwoLockPrinter(lockC, lockA, 'A'));
    // 列印b的執行緒
    Thread threadB = new Thread(new TwoLockPrinter(lockA, lockB, 'B'));
    // 列印c的執行緒
    Thread threadC = new Thread(new TwoLockPrinter(lockB, lockC, 'C'));

    // 依次開啟a b c執行緒
    threadA.start();
    Thread.sleep(100); // 確保按順序A、B、C執行
    threadB.start();
    Thread.sleep(100);
    threadC.start();
    Thread.sleep(100);
}

}