注:控制多线程顺序方法有很多不一样例举。写两个最顺手的,代码还有很大的优化空间
关键:必须掌握synchronized 关键字的wait(),notify,ReentrantLock类的await,signal使用就行了
1.控制2个线程顺序打印A、B
package com.wcc.demo.controller;
import java.util.concurrent.CountDownLatch;
class PrintAB {
private static Object obj = new Object();
//先控制先打印A
CountDownLatch cdl = new CountDownLatch(1);
public void printA() throws InterruptedException {
//同步锁的类,粒度太大,有待优化
synchronized (obj) {
for (int i = 0; i < 10; i++) {
cdl.countDown();
System.out.println("A");
//先唤醒B
obj.notify();
//然后等待释放锁
obj.wait();
}
//必须加 不然程序打印完会阻塞
obj.notify();
}
}
public void printB() throws InterruptedException {
synchronized (obj) {
for (int i = 0; i < 10; i++) {
cdl.await();
System.out.println("B");
obj.notify();
obj.wait();
}
//必须加 不然程序打印完会阻塞
obj.notify();
}
}
}
public class DxcPrintAB {
public static void main(String[] args) {
PrintAB printAB = new PrintAB();
new Thread(() -> {
try {
printAB.printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
printAB.printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
2.控制三个线程打印A、B、C
package com.wcc.demo.controller;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Print {
//标志位
int num = 1;
ReentrantLock lock = new ReentrantLock();
Condition cd1 = lock.newCondition();
Condition cd2 = lock.newCondition();
Condition cd3 = lock.newCondition();
//打印A
public void printA() throws InterruptedException {
lock.lock();
try {
//注意不要用if 防止虚假唤醒
while (num != 1) {
cd1.await();
}
System.out.println("A");
num = 2;
cd2.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
//打印B
public void printB() throws InterruptedException {
lock.lock();
try {
while (num != 2) {
cd2.await();
}
System.out.println("B");
num = 3;
cd3.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
//打印A
public void printC() throws InterruptedException {
lock.lock();
try {
while (num != 3) {
cd3.await();
}
System.out.println("C");
num = 1;
cd1.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
public class DxcPrintABC {
public static void main(String[] args) {
Print print = new Print();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
print.printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
print.printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
print.printC();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}