Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

# Leetcode 1115 交替打印 FooBar ( Print FooBar Alternately *Medium* ) 题解分析

发表于 2022-05-01 分类于 Java ， leetcode 阅读次数： 阅读次数： Disqus：
无聊随机了道并发题，还是比较明显的用信号量就可以解决的题，不过第一次做还是有点不适应，要加油多练练

无聊想去 roll 一题就看到了有并发题，就找到了这题，其实一眼看我的想法也是用信号量，但是用 condition 应该也是可以处理的，不过这类问题好像本地有点难调，因为它好像是抽取代码执行的，跟直观的逻辑比较不一样
Suppose you are given the following code:

    class FooBar {
      public void foo() {
        for (int i = 0; i < n; i++) {
          print("foo");
        }
      }

      public void bar() {
        for (int i = 0; i < n; i++) {
          print("bar");
        }
      }
    }

The same instance of `FooBar` will be passed to two different threads:

- thread `A` will call `foo()`, while
- thread `B` will call `bar()`.
  Modify the given program to output `"foobar"` n times.

### 示例

#### Example 1:

> Input: n = 1
> Output: “foobar”
> Explanation: There are two threads being fired asynchronously. One of them calls foo(), while the other calls bar().
> “foobar” is being output 1 time.

#### Example 2:

> Input: n = 2
> Output: “foobarfoobar”
> Explanation: “foobar” is being output 2 times.

### 题解

#### 简析

其实用信号量是很直观的，就是让打印 foo 的线程先拥有信号量，打印后就等待，给 bar 信号量 + 1，然后 bar 线程运行打印消耗 bar 信号量，再给 foo 信号量 + 1

#### code

    class FooBar {

        private final Semaphore foo = new Semaphore(1);
        private final Semaphore bar = new Semaphore(0);
        private int n;

        public FooBar(int n) {
            this.n = n;
        }

        public void foo(Runnable printFoo) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                foo.acquire();
            	// printFoo.run() outputs "foo". Do not change or remove this line.
            	printFoo.run();
                bar.release();
            }
        }

        public void bar(Runnable printBar) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                bar.acquire();
                // printBar.run() outputs "bar". Do not change or remove this line.
            	printBar.run();
                foo.release();
            }
        }
    }