LeetCode_1114.按順序打印(多線程)


LeetCode_1114

我們提供了一個類:

public class Foo {
    public void one() { print("one"); }
    public void two() { print("two"); }
    public void three() { print("three"); }
}
三個不同的線程將會共用一個 Foo 實例。

線程 A 將會調用 one() 方法
線程 B 將會調用 two() 方法
線程 C 將會調用 three() 方法
請設計修改程序,以確保 two() 方法在 one() 方法之后被執行,
three() 方法在 two() 方法之后被執行。

示例 1:

輸入: [1,2,3]
輸出: "onetwothree"
解釋: 
有三個線程會被異步啟動。
輸入 [1,2,3] 表示線程 A 將會調用 one() 方法,
線程 B 將會調用 two() 方法,線程 C 將會調用 three() 方法。
正確的輸出是 "onetwothree"。

示例 2:

輸入: [1,3,2]
輸出: "onetwothree"
解釋: 
輸入 [1,3,2] 表示線程 A 將會調用 one() 方法,
線程 B 將會調用 three() 方法,線程 C 將會調用 two() 方法。
正確的輸出是 "onetwothree"。

注意:

盡管輸入中的數字似乎暗示了順序,
但是我們並不保證線程在操作系統中的調度順序。
你看到的輸入格式主要是為了確保測試的全面性。

示例代碼:

class Foo {

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

方法一:使用鎖題解

  • 測試用例:36個
  • 執行用時:17ms
  • 內存消耗:35.8MB
class Foo {

    // 構造兩道屏障
    private boolean firstFinished;
    private boolean secondFinished;
    private Object lock = new Object();
    
    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        synchronized (lock) {
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            firstFinished = true;
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        synchronized (lock) {
            while (!firstFinished) {
                lock.wait();
            }
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            secondFinished = true;
            lock.notifyAll();
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        synchronized (lock) {
            while (!secondFinished) {
                lock.wait();
            }
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
        }
    }
}

方法二:通過信號量題解

  • 測試用例:36個
  • 執行用時:19ms
  • 內存消耗:36.1MB
import java.util.concurrent.Semaphore;

class Foo {
    
    Semaphore A;
    Semaphore B;
    Semaphore C;

    public Foo() {
        A = new Semaphore(1);
        B = new Semaphore(0);
        C = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        A.acquire();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        B.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        B.acquire();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        C.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        C.acquire();
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

方法三:使用 CountDownLatch 題解

  • 測試用例:36個
  • 執行用時:19ms
  • 內存消耗:36MB
import java.util.concurrent.CountDownLatch;

class Foo {

    CountDownLatch latch1;
    CountDownLatch latch2;
    
    public Foo() {
        latch1 = new CountDownLatch(1);
        latch2 = new CountDownLatch(2);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        latch1.countDown();
        latch2.countDown();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        latch1.await();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        latch2.countDown();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        latch2.await();
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM