Leetcode 1114 - 按序打印

Leetcode 1114 - 按序打印 - 題解以及解析
<!--more-->html

題目描述

咱們提供了一個類:java

public class Foo {
  public void one() { print("one"); }
  public void two() { print("two"); }
  public void three() { print("three"); }
}

三個不一樣的線程將會共用一個 Foo 實例。api

  • 線程 A 將會調用 one() 方法
  • 線程 B 將會調用 two() 方法
  • 線程 C 將會調用 three() 方法

請設計修改程序,以確保 two() 方法在 one() 方法以後被執行,three() 方法在 two() 方法以後被執行。併發

示例 1:oracle

  • 輸入: [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() {}

    private Semaphore first = new Semaphore(0);
    private Semaphore second = new Semaphore(0);
    private Semaphore third = new Semaphore(0);

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

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

    public void third(Runnable printThird) throws InterruptedException {
        // printThird.run() outputs "third". Do not change or remove this line.
        third.acquire();
        printThird.run();
        third.release();
    }
}
執行用時: 12 ms , 在全部 Java 提交中擊敗了 74.80% 的用戶

內存消耗: 39.3 MB , 在全部 Java 提交中擊敗了 5.60% 的用戶ui

題解反思

這道題主要的解題思路就是採用了三個初始化 permit0 的信號量。這樣在程序啓動時,剛開始 second.acquire() third.acquire() 均不會獲取到線程資源,直到 first 執行完 run() 方法後,纔會釋放第二個信號量,這時 second.acquire() 才能獲取到信號量,繼而 printSecond.run() ,以後 second 又會釋放第三個信號量,一樣這時 third.acquire() 纔可以獲取到信號量,從而成功執行 printThird.run(),經過這樣的方式,保證了線程的按許執行。this

這裏貼一下 Java 中信號量 Semaphore 的官方接口文檔,可供查閱。https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/Semaphore.html操作系統

在併發問題中,他們都有一個共同的特徵,即:多個線程/進程之間共享某些資源,從而致使併發訪問時的衝突。因爲在程序中沒法消除全部對共享資源的依賴,在這種狀況下,防止併發問題就變成了共享資源的協調問題了。所以,解決這類問題其中最核心的思想就是要保證共享資源在某個時刻只能有一個線程/進程訪問,也就是確保系統中關鍵代碼的獨佔性,這樣就能夠防止程序進入不一致的狀態。

最後,再推薦一篇信號量相關的教程。👉 Semaphores in Java

本文首發於「 愚一筆記
相關文章
相關標籤/搜索