错误示例
public class PrintABCUsingSingleThreadExecutor {
// 这种方式其实不是三个线程轮流输出,只是线程池的线程在输出
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
System.out.print(Thread.currentThread().getId()+"A");
});
Thread threadB = new Thread(() -> {
System.out.print(Thread.currentThread().getId()+"B");
});
Thread threadC = new Thread(() -> {
System.out.println(Thread.currentThread().getId()+"C");
});
// 单线程线程池输出
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
singleExecutor.execute(threadA);
singleExecutor.execute(threadB);
singleExecutor.execute(threadC);
}
//关闭线程池
singleExecutor.shutdown();
}
}
从输出结果看出是同一个线程在输出
实现思路:三个线程顺序输出ABC,类似顺序打开ABC三间房,B的钥匙在A那,C的钥匙在B那,A的钥匙在C那,同时开个后门> 开始的时候A门可以打开,不需要钥匙,后面就都是凭钥匙开门保证顺序。
方式一:synchronized + wait + notify
public class PrintABCUsingWaitNotify {
private int times;
private volatile int state;
private static final Object LOCK = new Object();
public PrintABCUsingWaitNotify(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingWaitNotify printABC = new PrintABCUsingWaitNotify(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
try {
print("A", 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printB() {
try {
print("B", 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printC() {
try {
print("C", 2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String name, int targetState) throws InterruptedException {
for (int i = 0; i < times; i++) {
synchronized (LOCK) {
while (state % 3 != targetState) {
LOCK.wait();
}
state++;
System.out.print(name);
LOCK.notifyAll();
}
}
}
}
方式二:ReentrantLock
public class PrintABCUsingLock {
private int times;
private int state;
private Lock lock = new ReentrantLock();
public PrintABCUsingLock(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingLock printABC = new PrintABCUsingLock(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
print("A", 0);
}
public void printB() {
print("B", 1);
}
public void printC() {
print("C", 2);
}
private void print(String name, int targetState) {
for (int i = 0; i < times; ) {
lock.lock();
if (state % 3 == targetState) {
state++;
i++;
System.out.print(name);
}
lock.unlock();
}
}
}
方式三:ReentrantLock + Condition
public class PrintABCUsingLockCondition {
private int times;
private int state;
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
public PrintABCUsingLockCondition(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingLockCondition printABC = new PrintABCUsingLockCondition(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
print("A", 0, conditionA, conditionB);
}
public void printB() {
print("B", 1, conditionB, conditionC);
}
public void printC() {
print("C", 2, conditionC, conditionA);
}
private void print(String name, int targetState, Condition current,
Condition next) {
for (int i = 0; i < times;) {
lock.lock();
try {
while (state % 3 != targetState) {
current.await();
}
state++;
i++;
System.out.print(name);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
方式四:LockSupport
public class PrintABCUsingLockSupport {
static Thread t1, t2, t3;
public static void main(String[] args) {
t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.print("A");
LockSupport.unpark(t2);
LockSupport.park();
}
});
t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
LockSupport.park();
System.out.print("B");
LockSupport.unpark(t3);
}
}
});
t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
LockSupport.park();
System.out.println("C");
LockSupport.unpark(t1);
}
}
});
t1.start();
t2.start();
t3.start();
}
}
方式五:CountDownLatch
package com.example.spring_boot_study.java8;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
/**
* 题目要求:ABC三个线程顺序执行10次
* 实现思路:使用 CountDownLatch 来实现:
* (1)定义dependLatch(所依赖的latch名)、selfLatch(自己的latch名)
* (2)首先调用所依赖的latch的await()方法,如果所依赖的latch的count为0,则重置所依赖的latch并打印需要输出的,最后将自身的count减去
* (3)sum为需要执行的次数
*/
public class PrintABCUsingCountDownLatch implements Runnable {
private static Map<String, CountDownLatch> countDownLatchMap = new HashMap<>();
private String dependLatch;
private String selfLatch;
private PrintABCUsingCountDownLatch(String dependLatch, String selfLatch) {
this.dependLatch = dependLatch;
this.selfLatch = selfLatch;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
countDownLatchMap.get(dependLatch).await();
countDownLatchMap.put(dependLatch, new CountDownLatch(1));
System.out.println(Thread.currentThread().getName() + ":" + selfLatch);
countDownLatchMap.get(selfLatch).countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String latchA = "A";
String latchB = "B";
String latchC = "C";
countDownLatchMap.put(latchA, new CountDownLatch(1));
countDownLatchMap.put(latchB, new CountDownLatch(1));
countDownLatchMap.put(latchC, new CountDownLatch(1));
//创建三个线程,但是此时由于三个CountDownLatch都不为0,所以三个线程都处于阻塞状态
Thread threadA = new Thread(new PrintABCUsingCountDownLatch(latchC, latchA));
Thread threadB = new Thread(new PrintABCUsingCountDownLatch(latchA, latchB));
Thread threadC = new Thread(new PrintABCUsingCountDownLatch(latchB, latchC));
threadA.start();
threadB.start();
threadC.start();
//latchC 阻塞了 latchA;调用latchC的countDown()方法,先让latchC为0,使latchA先运行
countDownLatchMap.get(latchC).countDown();
}
}
方式六:Semaphore
package com.tiger.thread;
import java.util.concurrent.Semaphore;
public class PrintABCUsingSemaphore {
private int times;
// 注意构造入参0和1的区别;这里也全部使用1实现
// 当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。也就是说参数为0,即表示调用了 acquire()。
private Semaphore semaphoreA = new Semaphore(1);
private Semaphore semaphoreB = new Semaphore(0);
private Semaphore semaphoreC = new Semaphore(0);
public PrintABCUsingSemaphore(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingSemaphore printABC = new PrintABCUsingSemaphore(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
try {
print("A", semaphoreA, semaphoreB);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printB() {
try {
print("B", semaphoreB, semaphoreC);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printC() {
try {
print("C", semaphoreC, semaphoreA);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String name, Semaphore current, Semaphore next)
throws InterruptedException {
for (int i = 0; i < times; i++) {
current.acquire();
if ("C".equals(name)){
System.out.println(name);
}else {
System.out.print(name);
}
next.release();
}
}
}
方式七:CyclicBarrier
package com.tiger.thread;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class PrintABCUsingCyclicBarrier {
private int times;
public PrintABCUsingCyclicBarrier(int times) {
this.times = times;
}
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
CyclicBarrier cyclicBarrier2 = new CyclicBarrier(3);
CyclicBarrier cyclicBarrier3 = new CyclicBarrier(3);
public static void main(String[] args) {
final PrintABCUsingCyclicBarrier printABC = new PrintABCUsingCyclicBarrier(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
private void printA() {
try {
print("A", cyclicBarrier, cyclicBarrier2, cyclicBarrier3);
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void printB() {
try {
print("B", cyclicBarrier, cyclicBarrier2, cyclicBarrier3);
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void printC() {
try {
print("C", cyclicBarrier, cyclicBarrier2, cyclicBarrier3);
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String word, CyclicBarrier cyclicBarrier, CyclicBarrier cyclicBarrier2, CyclicBarrier cyclicBarrier3) throws BrokenBarrierException, InterruptedException {
for (int i = 0; i < times; i++) {
cyclicBarrier.await();
if ("A".equals(word)) {
System.out.print(word);
}
cyclicBarrier2.await();
if ("B".equals(word)) {
System.out.print(word);
}
cyclicBarrier3.await();
if ("C".equals(word)) {
System.out.println(word);
}
}
}
}
方式八: Volatile
public class PrintABCUsingVolatile {
private int times;
private volatile int state;
public PrintABCUsingVolatile(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingVolatile printABC = new PrintABCUsingVolatile(10);
// 这里不考虑线程实际获取时间分片的问题,默认按代码顺序获取时间分片
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() { print("A", 0); }
public void printB() {
print("B", 1);
}
public void printC() {
print("C", 2);
}
private void print(String name, int targetState) {
for (int i = 0; i < times; ) {
// 不加锁无法保证if代码块的原子性
while (state % 3 != targetState) {
}
if ("C".equals(name)){
System.out.println(name);
}else {
System.out.print(name);
}
state++;
i++;
}
}
}
方式九:AtomicInteger(跟方式八区别不大)
public class PrintABCUsingAtomicInteger {
private int times;
public PrintABCUsingAtomicInteger(int times) {
this.times = times;
}
private static AtomicInteger state = new AtomicInteger(0);
public static void main(String[] args) {
PrintABCUsingAtomicInteger printABC = new PrintABCUsingAtomicInteger(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
print("A", 0);
}
public void printB() {
print("B", 1);
}
public void printC() {
print("C", 2);
}
private void print(String name, int targetState) {
for (int i = 0; i < times; ) {
// 不加锁无法保证if代码块的原子性
while (state.get() % 3 != targetState) {
}
if ("C".equals(name)) {
System.out.println(name);
} else {
System.out.print(name);
}
state.incrementAndGet();
i++;
}
}
}
方式十:BlockingQueue
package com.tiger.thread;
import java.util.concurrent.*;
public class PrintABCUsingBlockingQueue {
private int times;
public PrintABCUsingBlockingQueue(int times) {
this.times = times;
}
private static BlockingQueue blockingQueue = new ArrayBlockingQueue(30);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
blockingQueue.add("A");
blockingQueue.add("B");
blockingQueue.add("C");
}
PrintABCUsingBlockingQueue p = new PrintABCUsingBlockingQueue(10);
System.out.println(blockingQueue.size());
new Thread(p::printA).start();
new Thread(p::printB).start();
new Thread(p::printC).start();
}
private void printA() {
try {
while (blockingQueue.size() != 0) {
if (blockingQueue.size() % 3 == 0) {
System.out.print("A");
// 注意 System.out.print("A")需要放在Object poll = blockingQueue.poll()之前,否则可能乱序
Object poll = blockingQueue.poll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void printB() {
try {
while (blockingQueue.size() != 0) {
if (blockingQueue.size() % 3 == 2) {
System.out.print("B");
Object poll = blockingQueue.poll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void printC() {
try {
while (blockingQueue.size() != 0) {
if (blockingQueue.size() % 3 == 1) {
System.out.println("C");
Object poll = blockingQueue.poll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
方式十一:Exchanger
package com.tiger.thread;
import java.util.concurrent.Exchanger;
public class PrintABCUsingExchanger {
private int times;
public PrintABCUsingExchanger(int times) {
this.times = times;
}
private static Exchanger<Integer> exchangerA = new Exchanger<>();
private static Exchanger<Integer> exchangerB = new Exchanger<>();
private static Exchanger<Integer> exchangerC = new Exchanger<>();
public void printA() {
for (int i = 0; i < times; i++) {
try {
// 确保从A开始数据的传递
if (i == 0) {
System.out.print("A");
} else {
Integer state = exchangerC.exchange(0);
while (state != 3) {
}
System.out.print("A");
}
//交换
exchangerA.exchange(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printB() {
try {
for (int i = 0; i < times; i++) {
//交换
Integer state = exchangerA.exchange(0);
//等待
while (state != 1) {
}
//执行
System.out.print("B");
//第二次交换
exchangerB.exchange(2);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printC() {
try {
for (int i = 0; i < times; i++) {
Integer state = exchangerB.exchange(0);
while (state != 2) {
}
System.out.println("C");
// 最后一次循环不需要传递数据了,否则线程无法结束
if (i != times - 1) {
exchangerC.exchange(3);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
PrintABCUsingExchanger p = new PrintABCUsingExchanger(10);
new Thread(p::printA).start();
new Thread(p::printB).start();
new Thread(p::printC).start();
}
}
參考: