LeetCode From Easy To Hard No6[Easy]: Print in Order 按顺序执行线程

Suppose we have a class:

public class Foo {
  public void first() { print("first"); }
  public void second() { print("second"); }
  public void third() { print("third"); }
}

The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call third(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second().

 

Example 1:

Input: [1,2,3]
Output: "firstsecondthird"
Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.

Example 2:

Input: [1,3,2]
Output: "firstsecondthird"
Explanation: The input [1,3,2] means thread A calls first(), thread B calls third(), and thread C calls second(). "firstsecondthird" is the correct output.

 

Note:

We do not know how the threads will be scheduled in the operating system, even though the numbers in the input seems to imply the ordering. The input format you see is mainly to ensure our tests' comprehensiveness.

 

要求按顺序执行线程顺序打印出:first -> second -> third

主要用wait()和notifyAll()方法实现:

wait()方法:释放CPU执行权,释放对象锁

notifyAll(): 唤醒所有正在等待该对象锁的线程。

class Foo {
    // 定义两个标识控制second 和 third 运行顺序
    private boolean run2;
    private boolean run3;
    final private byte[] lock = new byte[1]; // 对象锁
    public Foo() {
        this.run2 = false;
        this.run3 = false;
    }

    public void first(Runnable printFirst) throws InterruptedException {
        synchronized (lock) {
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            run2 = true; // 设置second 方法为true跳过while循环直接打印结果
            lock.notifyAll();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        synchronized (lock) {
            while (!run2) {
                lock.wait(); // run2 为 false 时,线程等待,释放cpu执行权同时释放对象锁
            }
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            run3 = true; // 设置third方法为true跳过while循环直接打印结果
            lock.notifyAll();
        }

    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized (lock) {
            while (!run3) {
                lock.wait(); // run3 为 false 时,线程等待,释放cpu执行权同时释放对象锁
            }
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
        }
    }
}

自己做完又到了参考大佬们代码的时候:

大佬用的是java current 包的Semaphore类:

import java.util.concurrent.*;
class Foo {
    Semaphore run2, run3;

    public Foo() {
        run2 = new Semaphore(0);
        run3 = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        run2.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        run2.acquire();
        printSecond.run();
        run3.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        run3.acquire(); 
        printThird.run();
    }
}

关于Semaphore类,大佬的解释如下:

https://leetcode.com/problems/print-in-order/discuss/332890/Java-Basic-semaphore-solution-8ms-36MB

  1. Semaphore is a bowl of marbles (or locks in this case). If you need a marble, and there are none, you wait. You wait until there is one marble and then you take it. If you release(), you will add one marble to the bowl (from thin air). If you release(100), you will add 100 marbles to the bowl (from thin air).
  2. The thread calling third() will wait until the end of second() when it releases a '3' marble. The second() will wait until the end of first() when it releases a '2' marble. Since first() never acquires anything, it will never wait. There is a forced wait ordering.
  3. With semaphores, you can start out with 1 marble or 0 marbles or 100 marbles. A thread can take marbles (up until it's empty) or put many marbles (out of thin air) at a time

Semaphore 可以控制允许活动的线程数量也就是线程并发数量。new 的时候需要传递一个参数代表同一时间允许活动的线程数量。线程需要通过acquire()方法获取许可,如果允许活动线程数量为0,则调用acquire()之后,线程会进入等待队列,直到调用release()释放许可。上边解法new Semaphore(0),证明线程需要等待直到允许活动的线程数大于0,release() 方法可以解放一个线程,如果在此之前允许活动的线程数量为0,则会凭空添加一个允许活动的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值