• 多线程面试题(迅雷)


    编写一个程序,开启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查过了,没有找到精确唤醒方式!!!!!!!!!!!!!!!
  • 相关阅读:
    SQL Server存储过程(二)
    WPF 小知识 (设置背景图)
    关于SQL Server中索引使用及维护简介
    学习asp.net比较完整的流程(转)
    web开发常用默认端口
    接口和类的几大区别
    WEB建站规划之建站目的
    个人经验:页面无刷新传输数据的多种方法总结
    旅游电子商务探讨
    vs2008中文版提供下载(包含中文msdn)
  • 原文地址:https://www.cnblogs.com/liuzy2014/p/4800937.html
Copyright © 2020-2023  润新知