多线程面试题(迅雷)

编写一个程序,开启3个线程,这3个线程的ID分别为ABC,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC.依次递推。
 
我的思路是这样的:每个线程都有一个公用的锁,谁先拿到锁,谁就判断是不是该我输出ID,如果不是我输出,我就释放锁,并继续申请等待锁 (wait),如果是我输出,我就输出,并且释放锁并且唤醒那些正在等待申请锁的线程(notify),那如何控制 A->B->C->A这样的循环输出呢,因为被唤醒的线程是不确定的,如果A线程唤醒了C线程呢,那C线程必须判断是否输出,如果不该 轮到自己,就必须释放锁,而去唤醒别人,直到唤醒的线程就是B为止。
 
以下是我的实现:
public class ABCOutputThread implements Runnable{
    private static String now = "A";
    private final static String lock = "lock";
    private String name,next;
   
    public ABCOutputThread(String name,String next) {
        this.name = name;
        this.next = next;
    }
 
    @Override
    public void run() {
        int i=10;
        while(i>0){
            // System.out.print(this.name+" begin to get lock ");
            synchronized (lock) {
                // System.out.print(this.name+" get it ");
                if(this.name.equals(now)){
                    // System.out.print(this.name+" my turn ");
                    System.out.print(this.name);
                    now = next;
                    --i;
                    // System.out.print(this.name+" notify other wait thread ");
                    try {lock.notifyAll();} catch (IllegalMonitorStateException e) {e.printStackTrace();}
                }else{
                    // System.out.print(this.name+" not my turn and wait the other notify me ");
                    try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}
                }
            }
        }
    }
 
    public static void main(String[] args) {
        Thread t1 = new Thread(new ABCOutputThread("A","B"));
        Thread t2 = new Thread(new ABCOutputThread("B","C"));
        Thread t3 = new Thread(new ABCOutputThread("C","A"));
        t1.start();
        t2.start();
        t3.start();
    }
}
 
一开始我写的是lock.notify(),而不是lock.notifyAll(),以至于运行的时候只输出ABC,而没有循环10次的效果,但是debug下又能循环10次。这是为什么呢,后来在程序代码中加入了System.out.print调试语句,发现,notify只会唤醒一个线程,考虑这样一种场景:
1、A获得锁,成功输出A后释放了锁,唤醒一个线程
2、恰巧唤醒的是自己,发现不该轮到自己输出,就释放锁等待,但没有唤醒任何线程
3、同时BC在等待A唤醒,A没有唤醒任何人,它调用的是wait,故三个线程全部“睡着了”
 
notify是唤醒一个线程的意思,仅仅唤醒一个而已,唤醒的是别人还是自己,是不确定的,而如果notifyAll则会唤醒所有的线程,让所有的线程都有机会去争用锁,个人觉得这样做有浪费资源的嫌疑,接下来我会看看有没有办法就唤醒特定对象,做到精确唤醒。
 
baidu查过了,没有找到精确唤醒方式!!!!!!!!!!!!!!!
原文地址:https://www.cnblogs.com/liuzy2014/p/4800937.html