LeetCode 按序打印

第1114題java

咱們提供了一個類:

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"。
 

注意:

儘管輸入中的數字彷佛暗示了順序,可是咱們並不保證線程在操做系統中的調度順序。

你看到的輸入格式主要是爲了確保測試的全面性。

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/print-in-order

解題思路

  • 1.定義一個flag信號量及對象鎖lock
  • 2.定義三個方法first,second,third用來分別執行A,B,C三個線程,而且在run()前增長限制,執行後更新flag值。好比:first執行條件爲flag=0(即C線程執行完),A線程執行完後,flag設置爲1表示能夠執行B線程了
  • 3.經過以上設置,保存了A,B,C線程按順序執行,這裏題目要求從A線程要第一個執行,因此要把flag信號量初始值爲0

代碼實現

public class Sub1114 {
    public static void main(String[] args) throws InterruptedException {
        //測試用例字符串
        int[] runOrder = new int[]{2, 3, 1};

        //生成結果字符串
        StringBuffer result = new StringBuffer();

        Runnable one = () -> result.append("one");
        Runnable two = () -> result.append("two");
        Runnable three = () -> result.append("three");

        Foo foo = new Foo();

        Thread threads[] = new Thread[runOrder.length];
        for (int i = 0; i < runOrder.length; ++i) {
            Thread thread = null;
            if (runOrder[i] == 1) {
                thread = new FirstThread(foo, one);
            } else if (runOrder[i] == 2) {
                thread = new SecondThread(foo, two);
            } else if (runOrder[i] == 3) {
                thread = new ThirdThread(foo, three);
            }
            thread.start();
            threads[i] = thread;
        }

        //等侍全部線程執行完
        for (int i = 0; i < threads.length; i++) {
            threads[i].join();
        }

        //輸出結果串
        System.out.println(result.toString());
    }
}

class FirstThread extends Thread {
    Foo foo;
    Runnable runnable;

    public FirstThread(Foo h2o, Runnable runnable) {
        this.foo = h2o;
        this.runnable = runnable;
    }

    @Override
    public void run() {
        try {
            foo.first(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class SecondThread extends Thread {
    Foo foo;
    Runnable runnable;

    public SecondThread(Foo h2o, Runnable runnable) {
        this.foo = h2o;
        this.runnable = runnable;
    }

    @Override
    public void run() {
        try {
            foo.second(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ThirdThread extends Thread {
    Foo foo;
    Runnable runnable;

    public ThirdThread(Foo h2o, Runnable runnable) {
        this.foo = h2o;
        this.runnable = runnable;
    }

    @Override
    public void run() {
        try {
            foo.third(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Foo {
    //信號量
    private int flag = 0;
    //定義Object對象爲鎖
    private Object lock = new Object();

    public Foo() {
    }

    public void first(Runnable printFirst) throws InterruptedException {
        synchronized (lock) {
            //若是flag不爲0則讓first線程等待,while循環控制first線程若是不滿住條件就一直在while代碼塊中,防止出現中途跳入,執行下面的代碼,其他線程while循環同理
            while (flag != 0) {
                lock.wait();
            }

            printFirst.run();
            //定義成員變量爲 1
            flag = 1;
            //喚醒其他全部的線程
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        synchronized (lock) {
            //若是成員變量不爲1則讓二號等待
            while (flag != 1) {
                lock.wait();
            }

            printSecond.run();
            //若是成員變量爲 1 ,則表明first線程剛執行完,因此執行second,而且改變成員變量爲 2
            flag = 2;
            //喚醒其他全部的線程
            lock.notifyAll();
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized (lock) {
            //若是flag不等於2 則一直處於等待的狀態
            while (flag != 2) {
                lock.wait();
            }

            //若是成員變量爲 2 ,則表明second線程剛執行完,因此執行third,而且改變成員變量爲 0
            printThird.run();
            flag = 0;
            lock.notifyAll();
        }
    }
}

資料

相關文章
相關標籤/搜索