LeetCode 1114:按序打印
题目描述
给你一个类:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
三个不同的线程 A、B、C 将会共用一个 Foo 实例。
- 线程 A 将会调用 first() 方法
- 线程 B 将会调用 second() 方法
- 线程 C 将会调用 third() 方法
请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。
解题思路
本文重点介绍Semaphore的两个变种解法,第一种是常规接发,相当于3个线程,有一个充当主线程做if else判断,其他执行线程满足if条件执行acquire时,因为Semaphore变量为0所以会停止等待,等待类主线程执行release后,完成相应Semaphore的+1操作,对应线程可继续执行打印输出。最后不要忘记对在支路线程中对主线程的Semaphore进行release的+1操作,便于后续其他线程执行相似操作。
Semaphore的法二则更加简洁巧妙,原理也是按顺序一个线程先执行acquire,Semaphore为0时等待停止,后续对下一个Semaphore进行release,相当于通知下一个等待中的线程可以继续执行,以此来控制线程的打印顺序。
代码实现
Synchronized
class Foo {
private int i = 1;
private int n = 3;
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
while(i <= n){
synchronized(this){
if(i <= n && i % 3 == 1){
printFirst.run();
i++;
}
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
while(i <= n){
synchronized(this){
if(i <= n && i % 3 == 2){
printSecond.run();
i++;
}
}
}
}
public void third(Runnable printThird) throws InterruptedException {
while(i <= n){
synchronized(this){
if(i <= n && i % 3 == 0){
printThird.run();
i++;
}
}
}
}
}
ReentrantLock
class Foo {
private int i = 1;
private int n = 3;
private Lock lock = new ReentrantLock();
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
while(i <= n){
lock.lock();
try{
if(i <= n && i % 3 == 1){
printFirst.run();
i++;
}
}finally{
lock.unlock();
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
while(i <= n){
lock.lock();
try{
if(i <= n && i % 3 == 2){
printSecond.run();
i++;
}
}finally{
lock.unlock();
}
}
}
public void third(Runnable printThird) throws InterruptedException {
while(i <= n){
lock.lock();
try{
if(i <= n && i % 3 == 0){
printThird.run();
i++;
}
}finally{
lock.unlock();
}
}
}
}
CyclicBarrier
class Foo {
private int i = 1;
private int n = 3;
private CyclicBarrier cb = new CyclicBarrier(3);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
for(int i = 1;i <= n ;i++){
if(i<= n && i % 3 == 1){
printFirst.run();
}
try{
cb.await();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
for(int i = 1;i <= n ;i++){
if(i<= n && i % 3 == 2){
printSecond.run();
}
try{
cb.await();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
}
}
public void third(Runnable printThird) throws InterruptedException {
for(int i = 1;i <= n ;i++){
if(i<= n && i % 3 == 0){
printThird.run();
}
try{
cb.await();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
}
}
}
Semaphore法一
class Foo {
private int i = 1;
private int n = 3;
private Semaphore semaphore1 = new Semaphore(0);
private Semaphore semaphore2 = new Semaphore(0);
private Semaphore semaphore3 = new Semaphore(1);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
while(i <= n){
if(i<= n && i % 3 == 1){
semaphore1.acquire();
printFirst.run();
i++;
semaphore3.release();
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
while(i <= n){
if(i<= n && i % 3 == 2){
semaphore2.acquire();
printSecond.run();
i++;
semaphore3.release();
}
}
}
public void third(Runnable printThird) throws InterruptedException {
while(i <= n){
semaphore3.acquire();
if(i<= n && i % 3 == 0){
printThird.run();
i++;
semaphore3.release();
}else if(i<= n && i % 3 == 1){
semaphore1.release();
}else if(i<= n && i % 3 == 2){
semaphore2.release();
}
}
}
}
Semaphore法二
class Foo {
private int i = 1;
private int n = 3;
private Semaphore semaphore12 = new Semaphore(0);
private Semaphore semaphore23 = new Semaphore(0);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
semaphore12.release();
}
public void second(Runnable printSecond) throws InterruptedException {
semaphore12.acquire();
printSecond.run();
semaphore23.release();
}
public void third(Runnable printThird) throws InterruptedException {
semaphore23.acquire();
printThird.run();
}
}
总结
本题来源于Leetcode中 归属于多线程类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!
觉得本博客有用的客官,可以给个赞鼓励下! 嘿嘿