LeetCode1114. 按序打印
难度简单257
我们提供了一个类:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
三个不同的线程 A、B、C 将会共用一个 Foo
实例。
- 一个将会调用
first()
方法 - 一个将会调用
second()
方法 - 还有一个将会调用
third()
方法
请设计修改程序,以确保 second()
方法在 first()
方法之后被执行,third()
方法在 second()
方法之后被执行。
示例 1:
输入: [1,2,3]
输出: "firstsecondthird"
解释:
有三个线程会被异步启动。
输入 [1,2,3] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 second() 方法,线程 C 将会调用 third() 方法。
正确的输出是 "firstsecondthird"。
示例 2:
输入: [1,3,2]
输出: "firstsecondthird"
解释:
输入 [1,3,2] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 third() 方法,线程 C 将会调用 second() 方法。
正确的输出是 "firstsecondthird"。
提示:
- 尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
- 你看到的输入格式主要是为了确保测试的全面性。
CountDownLatch
countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
原理:
countDownLatch.countDown();// 数量-1
countDownLatch.await();// 等待计数器归零,然后再向下执行
每次有线程调用 countDown() 数量-1,假设计数器变为0,countDownLatch.await() 就会被唤醒,继续执行!
package Leetcode1114按序打印;
import java.util.concurrent.CountDownLatch;
public class CountDownLatch1 {
public static class Foo {
//初始化每个CountDownLatch的值为1,表示有一个线程执行完后,执行等待的线程
CountDownLatch countDownLatch1 = new CountDownLatch(1);
CountDownLatch countDownLatch2 = new CountDownLatch(1);
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
countDownLatch1.countDown();// 数量-1,计数器1归0了
}
public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove this line.
countDownLatch1.await();// 等待计数器1归零,然后再向下执行
printSecond.run();
countDownLatch2.countDown();// 数量-1,计数器2归0了
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
countDownLatch2.await();// 等待计数器2归零,然后再向下执行
printThird.run();
}
}
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(() -> {
try {
foo.first(new Runnable() {
@Override
public void run() {
System.out.println("first");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.second(new Runnable() {
@Override
public void run() {
System.out.println("second");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.third(new Runnable() {
@Override
public void run() {
System.out.println("third");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
Semaphore
Semaphore:信号量
原理:
semaphore.acquire()
获得,假设如果已经满了,等待,等待被释放为止!
semaphore.release();
释放,会将当前的信号量释放 + 1,然后唤醒等待的线程!
作用: 多个共享资源互斥的使用!并发限流,控制最大的线程数!
package Leetcode1114按序打印;
import java.util.concurrent.Semaphore;
public class Semaphore1 {
public static class Foo {
Semaphore s1 = new Semaphore(0);
Semaphore s2 = new Semaphore(0);
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 {
// printSecond.run() outputs "second". Do not change or remove this line.
s1.acquire();
printSecond.run();
s2.release();
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
s2.acquire();
printThird.run();
}
}
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(() -> {
try {
foo.first(new Runnable() {
@Override
public void run() {
System.out.println("first");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.second(new Runnable() {
@Override
public void run() {
System.out.println("second");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.third(new Runnable() {
@Override
public void run() {
System.out.println("third");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
Synchronized
package Leetcode1114按序打印;
public class Synchronized1 {
public static class Foo {
//控制变量
private int flag = 0;
//定义Object对象为锁
private Object lock = new Object();
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
synchronized (lock) {
while (flag != 0) {
lock.wait();
}
printFirst.run();
flag = 1;
lock.notifyAll();
}
}
public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove this line.
synchronized (lock) {
while (flag != 1) {
lock.wait();
}
printSecond.run();
flag = 2;
lock.notifyAll();
}
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
synchronized (lock) {
while (flag != 2) {
lock.wait();
}
printThird.run();
lock.notifyAll();
}
}
}
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(() -> {
try {
foo.first(new Runnable() {
@Override
public void run() {
System.out.println("first");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.second(new Runnable() {
@Override
public void run() {
System.out.println("second");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
foo.third(new Runnable() {
@Override
public void run() {
System.out.println("third");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}