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是真的有点复杂。希望此文能够对大家有所帮助。
网友评论