package com.likou;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;
/**
* TODO
* 从0到n递增数,使用三个线程,分别是线程A,线程B与线程C
* 线程A打印0,线程B打印奇数,线程C打印偶数.打印完一次奇数必须要打印一次0,打印一次偶数也必须打印一
* 奇数.
* 例:从0-5
* 0102030405这样
* @outhor qiangsw
* @date 2021/9/4 22:41
*/
public class ZeroEvenOdd {
public static void main(String[] args) {
ReentranZeroEvenOdd zeo = new ReentranZeroEvenOdd(10);
new Thread(() -> {
try {
zeo.zero(i -> {
System.out.print(i);
});
} catch (Exception e) {
}
}).start();
new Thread(() -> {
try {
zeo.even(i -> {
System.out.print(i);
});
} catch (Exception e) {
}
}).start();
new Thread(() -> {
try {
zeo.odd(i -> {
System.out.print(i);
});
} catch (Exception e) {
}
}).start();
}
}
/**
* 可重入锁 ReentrantLock
* Condition接口 多线程协调通信类工具 ReentrantLock的newCondition()方法是实现,内部也是AQS
* newCondition().await() 等待
* newCondition().await() 唤醒
* newCondition().await()与newCondition().await() 必须在
*/
class ReentranZeroEvenOdd {
private int n;
private AtomicInteger start = new AtomicInteger(1); //递增数
AtomicInteger flag = new AtomicInteger(0); //0奇偶数标识
private Lock lock = new ReentrantLock(); //锁
final Condition zeroCondition = lock.newCondition();
final Condition evenCondition = lock.newCondition();
final Condition oddCondition = lock.newCondition();
public ReentranZeroEvenOdd(int n) {
this.n = n;
}
/**
* while循环,循环条件是递增数start<n.如果start>n,循环结束
*
* 判断0奇偶数标识flag!=0, zeroCondition等待.线程处于等待
* 判断0奇偶数标识flag==0 ,执行 printNumber.accept(0)
*
* @param printNumber
* @throws InterruptedException
*/
public void zero(IntConsumer printNumber) throws InterruptedException {
lock.lock(); //获取锁
try {
while (start.get() <= n) {
if (flag.get() != 0) { //flag!=0 一直处于等待状态
zeroCondition.await();
}
printNumber.accept(0);
if ((start.get() & 1) == 1) { //判断是否是奇数
flag.compareAndSet(0, 1); //cas原理flag设置2 奇数
oddCondition.signal();
} else { //判断是否是偶数
flag.compareAndSet(0, 2); //cas原理flag设置2 偶数
evenCondition.signal();
}
zeroCondition.await(); //唤醒0锁
}
oddCondition.signal(); //唤醒奇数锁
evenCondition.signal(); //唤醒偶数锁
} finally {
lock.unlock(); //释放锁
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
lock.lock();
try {
while (start.get() <= n) {
if (flag.get() != 2) {
evenCondition.await();
} else {
printNumber.accept(start.getAndIncrement());
flag.compareAndSet(2, 0);
zeroCondition.signal();
}
}
} finally {
lock.unlock();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
lock.lock();
try {
while (start.get() <= n) {
if (flag.get() != 1) {
oddCondition.await();
} else {
printNumber.accept(start.getAndIncrement());
flag.compareAndSet(1, 0);
zeroCondition.signal();
}
}
} finally {
lock.unlock();
}
}
}
交替打印字符串:力扣
package com.likou;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;
/**
* @ClassName
* @Description
* @Author qiangsw
* @date 2021/9/20 13:40
* @Version 1.0
* TODO
* 交替打印字符串
* https://leetcode-cn.com/problems/fizz-buzz-multithreaded/
*/
public class ReentrantLockFizzBuzz {
public static void main(String[] args) {
FizzBuzz fizzBuzz = new FizzBuzz(15);
new Thread(() -> {
try {
fizzBuzz.fizz(() -> {
System.out.println(fizzBuzz.start.get() + ":fizz");
});
} catch (Exception e) {
}
}).start();
new Thread(() -> {
try {
fizzBuzz.buzz(() -> {
System.out.println(fizzBuzz.start.get() + ":buzz");
});
} catch (Exception e) {
}
}).start();
new Thread(() -> {
try {
fizzBuzz.fizzbuzz(() -> {
System.out.println(fizzBuzz.start.get() + ":fizzbuzz");
});
} catch (Exception e) {
}
}).start();
new Thread(() -> {
try {
fizzBuzz.number(i -> {
System.out.println(fizzBuzz.start.get() + ":" + i);
});
} catch (Exception e) {
}
}).start();
// System.out.println(11 % 3 +","+ 11 % 5);
}
}
class FizzBuzz {
private int n;
public AtomicInteger start = new AtomicInteger(1);
private Lock lock = new ReentrantLock();
Condition fizzCon = lock.newCondition();
Condition buzzCon = lock.newCondition();
Condition fizzbuzzCon = lock.newCondition();
Condition numCon = lock.newCondition();
public FizzBuzz(int n) {
this.n = n;
}
public void fizz(Runnable printFizz) throws InterruptedException {
try {
lock.lock();
while (start.get() <= n) {
if (start.get() % 3 == 0 && start.get() % 5 != 0) {
printFizz.run();
start.incrementAndGet();
buzzCon.signal();
fizzbuzzCon.signal();
numCon.signal();
} else {
buzzCon.signal();
fizzbuzzCon.signal();
numCon.signal();
fizzCon.await();
}
}
} finally {
lock.unlock();
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
try {
lock.lock();
while (start.get() <= n) {
if (start.get() % 5 == 0 && start.get() % 3 != 0) {
printBuzz.run();
start.incrementAndGet();
fizzbuzzCon.signal();
fizzCon.signal();
numCon.signal();
} else {
fizzbuzzCon.signal();
fizzCon.signal();
numCon.signal();
buzzCon.await();
}
}
} finally {
lock.unlock();
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
try {
lock.lock();
while (start.get() <= n) {
if (start.get() % 3 == 0 && start.get() % 5 == 0) {
printFizzBuzz.run();
start.incrementAndGet();
buzzCon.signal();
fizzCon.signal();
numCon.signal();
} else {
buzzCon.signal();
fizzCon.signal();
numCon.signal();
fizzbuzzCon.await();
}
}
} finally {
lock.unlock();
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
try {
lock.lock();
while (start.get() <= n) {
if (start.get() % 3 != 0 && start.get() % 5 != 0) {
printNumber.accept(start.get());
start.incrementAndGet();
fizzbuzzCon.signal();
fizzCon.signal();
buzzCon.signal();
} else {
numCon.await();
}
}
} finally {
lock.unlock();
}
}
}