leecode-1114:按序打印

leecode最近多了个多线程模块,虽然目前只有四个题目,但是也是常见的面试中会遇到的四个题目。本文将讲解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"。

注意:

尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。

你看到的输入格式主要是为了确保测试的全面性。


题目分析

题目的大意是指不管线程调用哪个方法,最终输出的顺序一定是"onetwothree",也就是方法 one() -> two() -> three()这种执行顺序。

这种可以使用到线程间的通信,使用wait,notify,但是对于三个线程来说有点难处理。如果想到了JUC包下的三个工具,CountDownLatch(闭锁),CyclicBarrier(栅栏), Semaphore(信号量)
,实现起来会更加简单。

CountDownLatch(闭锁),CyclicBarrier(栅栏), Semaphore(信号量)

  • CountDownLatch(闭锁)

    特点:控制线程的执行顺序。不可重用
    场景:初始化参数为3,则线程4,需要等到线程1,线程2,线程3执行完后,才会执行线程4,从而保证有序性。

  • CyclicBarrier(栅栏)

    特点:多个线程的状态一致时,同时执行。可重用
    场景:线程1,线程2都进入了就绪状态后,同时进入到运行状态。

  • Semaphore(信号量)

    特点:控制同时允许线程的数量。可重用
    场景:初始量为3,则表示同一时间只能有3个线程执行,其余的线程需要等待。当有个线程执行完后,等待的线程选择一个进入允许状态。

解决

通过上面对三个工具类的了解,我们可以使用countDownLatch来实现。

two()方法等待one()的闭锁
three()方法等待two()的闭锁

import java.util.concurrent.CountDownLatch;

class Foo {

    private CountDownLatch firstCount = new CountDownLatch(1);
    private CountDownLatch secondCount = new CountDownLatch(1);

    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {

        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        firstCount.countDown();
    }

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

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

执行结果

通过

总结

本文通过工具类来实现貌似体现不出来改题目考核的目的,但是如果真的通过wait,notify是真的有点复杂。希望此文能够对大家有所帮助。

你可能感兴趣的:(leecode-1114:按序打印)