- Print类提供打印两个数字和一个字母的同步方法,这样就能通过Print对象的同步锁机制保证输出数字和字母的顺序符合要求。
public class Print {
private boolean flag = false;
private int number = 1;
private char c = 'A';
synchronized public boolean numberPrint() throws Exception{
boolean b = false;
if(!flag){
for(int i = 0; i < 2; i++){
System.out.print(number++);
}
// 用来判断并返回给线程执行体是否输出结束了。
if(number == 53){
b = true;
}
else{
b = false;
}
flag = true;
notifyAll();
}
else{
wait();
}
return b;
}
synchronized public boolean charPrint() throws Exception{
boolean b = false;
if(flag){
System.out.print(c++);
// 用来判断并返回给线程执行体是否输出结束了。
if(c == 'Z' + 1){
b = true;
}
else{
b = false;
}
flag = false;
notifyAll();
}
else{
wait();
}
return b;
}
}
- 创建两个线程类,分别负责输出数字和字母
输出数字:
public class NumberThread extends Thread {
private Print print;
public NumberThread(Print print, String name){
super(name);
this.print = print;
}
public void run(){
try{
boolean b = false;
/* 这里一开始用的是for循环26次,发现结果输出到2526M就没了,而且进入阻塞状 态。后改为52,倒是全都输出了,可还是阻塞。*/
/*之所以会这样,是因为你无法确切的知道执行每几次numberPrint()方法才输出1个数字,可能是1次,可能是两次。因为,每次进入numberPrint()后,都要根据旗标flag判断是输出还是等待,有可能,系统线程分配的很好,每次进入时,flag都是输出,也有可能会连续进去两次,一次输出,第二次wait(),所以就无法知道应该执行多少次才符合要求,所以要用while(b)*/
while(!b){
b = print.numberPrint();
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
输出字母:
public class CharThread extends Thread {
private Print print;
public CharThread(Print print, String name){
super(name);
this.print = print;
}
public void run(){
try{
boolean b = false;
while(!b){
b = print.charPrint();
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
主类:
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
new NumberThread(print, "number").start();
new CharThread(print, "char").start();
}
}
所以疯狂java讲义上的那个例子,解释的是不清楚的,for循环100次取钱操作不代表每次都能取出钱,可能实际上只有50次取钱时成功的,也有可能是50到100之间的某个数。