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中的静态变量
}
/**
* 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 多线程顺序打印ABC
- java多线程顺序打印ABC
- java多线程面试题:三个线程顺序打印ABC,重复10次
- Java多线程 循环打印ABC 10次
- java多线程---顺序打印ABC的三种实现---ReentrantLock方式
- java多线程编程之连续打印abc的几种解法
- Java多线程循环打印ABC 10次,可能是东半球最美解决方案了
- JAVA 多线程轮流打印ABC
- 顺序打印ABC------java多线程的一道经典面试题
- java多线程---顺序打印ABC的三种实现---join方法
- JAVA 多线程开篇 -从按顺序打印ABC开始
- 迅雷笔试题 (JAVA多线程)启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC
- java多线程---顺序打印ABC的三种实现---volatile方式
- Java多线程:用三个线程控制循环输出10次ABC
- 多线程(至少三个线程)分别打印A、B、C,要求按ABC的顺序循环打印10次。
- java 实现3个线程 依次打印ABC,并且循环10次
- 使用Java 多线程编程 让三个线程轮流输出ABC,循环10次后结束
- Java实现多线程经典问题:使用三个线程实现输出ABCABC循环
- 多线程顺序打印ABC
- java并发---三线程打印ABC的问题