首页 > 代码库 > 关于线程的一到面试题

关于线程的一到面试题

节录于<<张孝祥-Java多线程与并发库高级应用>>

题目概述

主线程执行10次 然后子线程执行5次 接着主线程再执行10次 子线程执行5次....一直循环50次。

首先我们应该明白我们的线程逻辑在于
"主线程执行10次 然后子线程执行5次"
至于循环50次不是我们最核心的业务逻辑。
因而我们先把"主线程执行10次 然后子线程执行5次"放到一个类中。

第一步

class Business{
     public  void main(int j){  //j作为最大的那个50次循环
     for(int i=1;i<=10;i++)
         System.out.println("main "+i+" of loop "+j);
     }

     public  void sub(int j){  //j作为最大的那个50次循环
     for(int i=1;i<=5;i++)
         System.out.println("sub "+i+" of loop "+j);
     }
}
然后就简单了,我们做出调用的类
public class TraditionalCommunication{
     public static void main(String[] args){
           final Business b=new Business();
       
       new Thread(
           new Runnable(){
             public void run(){
            for(int i=1;i<=50;i++)
               b.sub(i);
         }
           }
       ).start();
    for(int i=1;i<=50;i++)
       b.main(i);
     }
}

如果就是现在这个代码去运行。看到的结果肯定是杂乱无章的。

可能父线程刚走了一圈(输出了一行代码),子线程就抢过了执行权。

第二步

所以只是我们得给business的两个方法,main与sub加上synchronized。

这个时候再测试,最起码两个线程(父线程子线程)不会互相干扰(互斥),但是还有可能父线程接连着运行了两圈(输出了20行代码)也就是说,我们让两个线程能互斥,但是不能协调的通信。(他们没有交替输出!)

第三步

class Business{
     
      private boolean shouldsub=true;  //这个变量名 起的很不错
     public synchronized void main(int j){  //j作为最大的那个50次循环
     if(shouldsub){
    try{
        this.wait();
    }catch(Exception e){ }
     }
     for(int i=1;i<=10;i++)
         System.out.println("main "+i+" of loop "+j);
     shouldsub=true;  //父线程已经执行了一次 所以shouldsub为true 该子线程执行了
     this.notify();
     }

     public synchronized void sub(int j){  //j作为最大的那个50次循环
     if(!shouldsub){
    try{
        this.wait();
    }catch(Exception e){ }
     }
     for(int i=1;i<=5;i++)
         System.out.println("sub "+i+" of loop "+j);
     shouldsub=false;  //子线程已经执行了一次 所以shouldsub为false 不能再执行了
     this.notify();
     }
}


这下OK了。大家看看还有可以修改的地方么?
     if(!shouldsub){
    try{
        this.wait();
    }catch(Exception e){ }
     }
应该改成下面的形式
     while(!shouldsub){
    try{
      this.wait();
    }catch(Exception e){}
     }


为什么?
因为有的时候线程会被"假唤醒",用while循环可以再判断一回。

其实写完代码,我仍然觉得这个题的关键就是把business类抽象出来,提炼出真正核心的业务逻辑

关于线程的一到面试题