您的位置:首页 > 编程语言 > Java开发

JAVA多线程打印ABC

2016-08-31 21:53 375 查看
多线程中一个很有名的例题就是多线程打印ABC,要求用三个线程,分别是打印A,打印B,打印C,轮流唤醒和锁死,最终打印出10组ABC。

/**
* Created by 123 on 2016/8/30.
*/
public class PrintABC {
public static void main(String[] args) {
ABC p = new ABC('A');//以A作为开始
new Print1(p).start();//启动打印A的线程,以p作为控制
new Print2(p).start();
new Print3(p).start();
}
}

//将打印A,打印B,打印C分别列为三个互斥的方法,写在类ABC中

class ABC {
char now; //当前需要打印的字母是now

public ABC(char now) {
this.now = now;
}

public synchronized void PrintA() { //打印A的方法,它与打印其它两个字母的方法互斥
if (now != 'A') { //如果线程被唤醒后发现当前需要打印的字母不是A
try { //就让这个线程wait(),继续进入等待池
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (now == 'A') { //如果当前需要打印的字母是A
System.out.print('A'); //打印A
now = 'B'; //将需要打印的字母置为B
Print1.cnt1--; //打印次数减1,cnt1是Print1中的静态变量
}
notify(); //再从等待池中唤醒一个线程
}

public synchronized void PrintB() { //同理
if (now != 'B') {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (now == 'B') {
System.out.print('B');
now = 'C';
Print2.cnt2--;
}
notify();
}

public synchronized void PrintC() { //同理
if (now != 'C') {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (now == 'C') {
System.out.print('C');
now = 'A';
Print3.cnt3--;
}
notify();
}
}

class Print1 extends Thread { //打印A的线程
ABC p = null;
public static int cnt1=10;
public Print1(ABC p) {
this.p = p;
} //构造方法,将ABC那个类传进来
//三个线程共用那一个类
@Override
public void run() {
while (cnt1 > 0) {
p.PrintA(); //一直打印,打印十次
//PrintA并不是打印了A,只是尝试打印A
//cnt1--是在PrintA中确保打印成功了以后再执行的
}
}
}

class Print2 extends Thread { //同理
ABC p = null;
public static int cnt2=10;
public Print2(ABC p) {
this.p = p;
}

@Override
public void run() {
while (cnt2 > 0) {
p.PrintB();
}
}
}

class Print3 extends Thread { //同理
ABC p = null;
public static int cnt3=10;
public Print3(ABC p) {
this.p = p;
}

@Override
public void run() {
while (cnt3 > 0) {
p.PrintC();
}
}
}
由于notify的唤醒是随机的,所以如果这里不加if判断的话,可能打印完A后唤醒了打印C的线程,这样就wait()完了以后就又打印了一个C,就乱套了,这就是多线程的一个Bug。
if (now == 'A') { //如果当前需要打印的字母是A
System.out.print('A'); //打印A
now = 'B'; //将需要打印的字母置为B
Print1.cnt1--; //打印次数减1,cnt1是Print1中的静态变量
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 多线程