在网上看了一道面试题 ,亲手做了一下,代码如下,但是运行不成功,有两个问题,
第一,为什么去掉类Business类中的方法前的synchronized关键字,会报错。该程序中,每个方法只被一个线程访问,没有多线程访问同一个方法啊,所以没必要加该关键字吧
第二,为什么输出结果不能循环到十次,好像就死锁了
请高人指点
//有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC…
package thread;public class Xunlei{ public static void main(String[] args) {

final Business bn = new Business();
new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10;i++){
bn.readA();
}
}
}).start();

new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<10;i++){
bn.readB();
}
}
}).start();

new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<5;i++){
bn.readC();
}
}
}).start();
}}class Business{
private int j=1;
public synchronized void readA(){
if(j==1){
System.out.print("A");
j=2;
notifyAll();
}

try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public synchronized void readB(){
if(j==2){
System.out.print("B");
j=3;
notifyAll();
}

try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public synchronized void readC(){
if(j==3){
System.out.print("C");
j=1;
notifyAll();
}

try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

解决方案 »

  1.   

    补充:更正如下红色部分(粘程序时忘了改过来)
    问题如上所描述,请指点
    new Thread(new Runnable(){
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    bn.readC();
    }
    }
    }).start();
      

  2.   

    IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。因为你3个线程都在一个(bn = new Business())对象上,而wait()都是在一个对象上作用,所以有问题。
      

  3.   

    我都是9次,很规矩。问题的原因是根据你代码的逻辑,你的最后一次的wait,再也没有人去notifyAll了。
      

  4.   

    我看来看去,知道为什么了,问题在于你用了双重控制机制。比如你在readA中,notifyA,但是可能第一个得到执行的是readC,那么因为它不符合j==3,所以就浪费了一次执行。所以造成你7、8、9的问题。而最终由于最后一次的wait,再也没有人去notifyAll了(readABC都在wait中),所以无法正常结束。
      

  5.   


    问题很明显啊,我在7楼已经说了,你的程序逻辑设计有问题,不信你运行我这个程序,就能看得很明白了,所有顺序都会显示出来,你就会发现是乱序的:
    public class TenThread {    public static void main(String[] args) {        final Business bn = new Business();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        bn.readA(i);
                    }
                }
            }).start();        new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        bn.readB(i);
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        bn.readC(i);
                    }
                }
            }).start();    }}class Business {
        private int j = 1;    public synchronized void readA(int i) {
            if (j == 1) {
                System.out.print(i + "A");
                j = 2;
                notifyAll();
            }
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    }    public synchronized void readB(int i) {
            if (j == 2) {
                System.out.print(i + "B");
                j = 3;
                notifyAll();
            }
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    }    public synchronized void readC(int i) {
            if (j == 3) {
                System.out.print(i + "C");
                j = 1;
                notifyAll();
            }
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }    }}
      

  6.   

    你还是把原题说出来吧,直接按目标实现就好了。是不是3个线程轮流输出ABC啊?
      

  7.   


    主类可以不需要修改,Business修改成下面这样就可以了。class Business {
        private int j = 1;    public synchronized void readA(int i) {
            while (true) {
                if (j == 1) {
                    System.out.print(i + "A");
                    j = 2;
                    notifyAll();
                    break;
                } else {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }    public synchronized void readB(int i) {
            while (true) {
                if (j == 2) {
                    System.out.print(i + "B");
                    j = 3;
                    notifyAll();
                    break;
                } else {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }    public synchronized void readC(int i) {
            while (true) {
                if (j == 3) {
                    System.out.print(i + "C");
                    j = 1;
                    notifyAll();
                    break;
                } else {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }}
      

  8.   


    有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC…
      

  9.   

    这个需求很简单,可以简化实现:public class TenThread extends Thread {    private static final int THREAD_NUM = 3;
        
        private static int token = 0;    private int tid = -1;    public static void main(String[] args) {
            for (int i = 0; i < THREAD_NUM; i++) {
                TenThread t = new TenThread(i);
                t.start();
            }
        }    TenThread(int tid) {
            super(String.valueOf((char) (tid + 'A')));
            this.tid = tid;
        }    public void run() {
            int cnt =0;
            while (cnt < 10){
                if ((token % THREAD_NUM) == tid) {
                    System.out.print(cnt + this.getName());
                    token++;
                    cnt++;
                }
            }
        }
    }