多线程的交替必然涉及到线程通信的问题。为了更直观的显示效果,打印轮数也打印出来,即每次打印完C后打印对应轮数打印效果如下:
1、使用同步方法,即synchronized关键字:
public class TestPrintABC1 {
public static void main(String[] args) {
ABCDemo1 emo = new ABCDemo1();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
emo.printA();
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
emo.printB();
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
int loopCount = i + 1;
emo.printC(loopCount);
}
}
}, "C").start();
}
}
class ABCDemo1 {
private int flag = 1;// 控制当前执行的线程的标记
public synchronized void printA() {// 打印A的方法
while(flag!=1) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName());
flag=2;
this.notifyAll();
}
public synchronized void printB() {// 打印B的方法
while(flag!=2) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName());
flag=3;
this.notifyAll();
}
public synchronized void printC(int loopCount) {// 打印C的方法
while(flag!=3) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" 第"+loopCount+"轮");
flag=1;
this.notifyAll();
}
}
2、使用重入锁Lock:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestPrintABC {
public static void main(String[] args) {
ABCDemo emo = new ABCDemo();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
emo.printA();
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
emo.printB();
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
int totalLoop = i + 1;
emo.printC(totalLoop);
}
}
}, "C").start();
}
}
class ABCDemo {
private char flag = 'a';// 控制当前执行的线程的标记
// 使用同步锁的方式解决线程安全问题,flag是共享数据
private Lock lock = new ReentrantLock();
// 使用Condition接口的相关方法来实现线程通信
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void printA() {// 打印A的方法
lock.lock();
try {
if (flag != 'a') {
condition1.await();
}
System.out.print(Thread.currentThread().getName());
flag = 'b';
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() {// 打印B的方法
lock.lock();
try {
if (flag != 'b') {
condition2.await();
}
System.out.print(Thread.currentThread().getName());
flag = 'c';
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(int loopCount) {// 打印C的方法
lock.lock();
try {
if (flag != 'c') {
condition3.await();
}
System.out.println(Thread.currentThread().getName() + " 第" + loopCount + "轮");
flag = 'a';
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}