1114. 按序打印

题目

我们提供了一个类:

1
2
3
4
5
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
4
5
6
输入: [1,2,3]
输出: "onetwothree"
解释:
有三个线程会被异步启动。
输入 [1,2,3] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 two() 方法,线程 C 将会调用 three() 方法。
正确的输出是 "onetwothree"。

示例2:

1
2
3
4
5
输入: [1,3,2]
输出: "onetwothree"
解释:
输入 [1,3,2] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 three() 方法,线程 C 将会调用 two() 方法。
正确的输出是 "onetwothree"。

提示:

  • 尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
  • 你看到的输入格式主要是为了确保测试的全面性。

解法

解法一:

while循环死等

JAVA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Foo {
private transient int flag = 1;

public Foo() {

}

public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this
// line.
printFirst.run();
flag = 2;
}

public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove
// this line.
while (true) {
if (2 == flag) {
break;
}
}
printSecond.run();
flag = 3;

}

public void third(Runnable printThird) throws InterruptedException {
while (true) {
if (3 == flag) {
break;
}
}
// printThird.run() outputs "third". Do not change or remove
// this line.
printThird.run();

}
}

解法二:

使用Condition做精准唤醒

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Foo {
private int flag = 1;
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();

public Foo() {

}

public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
try {
lock.lock();
printFirst.run();
flag = 2;
condition1.signal();
} finally {
lock.unlock();
}
}

public void second(Runnable printSecond) throws InterruptedException {
try {
lock.lock();
if (2 != flag) {
condition1.await();
}

// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
flag = 3;
condition2.signal();
} finally {
lock.unlock();
}

}

public void third(Runnable printThird) throws InterruptedException {
try {
lock.lock();
if (3 != flag) {
condition2.await();
}
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
} finally {
lock.unlock();
}
}
}

解法三:

使用wait和notify

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Foo {
private int flag = 1;

private Object lock = new Object();

public Foo() {

}

public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this
// line.
synchronized(lock) {
while (1 != flag) {
lock.wait();
}
printFirst.run();
flag = 2;
lock.notifyAll();
}

}

public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove
// this line.
synchronized(lock) {
while (2 != flag) {
lock.wait();
}
printSecond.run();
flag = 3;
lock.notifyAll();
}
}

public void third(Runnable printThird) throws InterruptedException {
synchronized(lock) {
while (3 != flag) {
lock.wait();
}
// printThird.run() outputs "third". Do not change or remove
// this line.
printThird.run();
flag = 3;
}
}
}

解法四:

使用CountDownLatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Foo {
private CountDownLatch c1 = new CountDownLatch(1);
private CountDownLatch c2 = 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();
c1.countDown();
}

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

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

解法五:

使用Semaphore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Foo {
private Semaphore s1 = new Semaphore(0);
private Semaphore s2 = new Semaphore(0);

public Foo() {
}

public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this
// line.
printFirst.run();
s1.release();;
}

public void second(Runnable printSecond) throws InterruptedException {
s1.acquire();;
// printSecond.run() outputs "second". Do not change or remove
// this line.
printSecond.run();
s2.release();;
}

public void third(Runnable printThird) throws InterruptedException {
s2.acquire();
// printThird.run() outputs "third". Do not change or remove
// this line.
printThird.run();
s2.release();
}
}
0%