Java并发库(四):传统线程同步通信技术

来源:互联网 发布:mysql批量insert into 编辑:程序博客网 时间:2024/06/10 05:17

深切怀念传智播客张孝祥老师,特将其代表作——Java并发库视频研读两遍,受益颇丰,记以后阅

04. 传统线程同步通信技术

       面试题,子线程10次与主线程100次来回循环执行50次

       下面是我刚看完面试题就暂停视频自己试着写的代码,还可以,结果完成要求了

在单次循环结束后让这个刚结束循环的线程休眠,保证另一个线程可以抢到执行权。

public class ThreadInterViewTest

{

       /**

        * 刚看到面试题没看答案之前试写

        * 子线程循环10次,回主线程循环100次,

        * 再到子线程循环10次,再回主线程循环100次

        * 如此循环50次      

        */

       publicstatic void main(String[] args)

       {

              intnum = 0;

              while(num++<50)//这种方法不好,new出来了50个线程

              {

                     newThread(new Runnable()

                                   {

                                          @Override

                                          public void run()

                                          {

                                                 circle("子线程运行", 10);

                                          }

                                   }).start();

                     try

                     {

                            //加这句是保证上边的子线程先运行,刚开始没加,主线程就先开了

                            Thread.sleep(2000);

                     }catch (InterruptedException e)

                     {

                            e.printStackTrace();

                     }

                     circle("主线程", 100);  

              }

       }

      

       publicstatic synchronized void circle(String name, int count)

       {

              for(int i=1; i<=count; i++)

              {

                     System.out.println(name+"::"+i);

              }

              try

              {

                     Thread.sleep(5000);

              }catch (InterruptedException e)

              {

                     e.printStackTrace();

              }

       }

}

 

张老师讲的方法:

1、将子线程和主线程中要同步的方法进行封装,加上同步关键字实现同步

2、两个线程间隔运行,添加一个标记变量进行比较以实现相互通信,加色的部分

wait   notify  notifyAll    wait会抛出异常

class Business

{

       private boolean bShouleSub = true;

       publicsynchronized void sub()

       {

              if (bShouleSub)

此处使用while以增加程序健壮性,因为存在虚假唤醒,有时候并没有被notify就醒了。如果该方法没有同步的话,此处就更要使用while进行判断了,避免进程不同步问题


              {

                     for (int i=1; i<11; i++)

                     SOP(sub+i);

              bShouldSub= false;

              this.notify();

}

else

       this.wait();

}

       publicsynchronized void main()

       {

              if (!bShouldSub)

              {

                     for (int i=1; i<101; i++)

                     SOP(main+i);

              bShouldSub= true;

              this.notify();

}

else

       this.wait();

}

}

经验:要用到共同数据(包括同步锁)或相同算法的多个方法要封装在一个类中

       锁是上在代表要操作的资源类的内部方法中的,而不是上在线程代码中的。这样写出来的类就是天然同步的,只要使用的是同一个new出来的对象,那么这个对象就具有同步互斥特性

       判断唤醒等待标记时使用while增加程序健壮性,防止伪唤醒

public class TraditionalThreadCommunication{

 

       /**

        * @param args

        */

       publicstatic void main(String[] args) {

             

              finalBusiness business = new Business();

              newThread(

                            newRunnable() {

                                  

                                   @Override

                                   publicvoid run() {

                                  

                                          for(int i=1;i<=50;i++){

                                                business.sub(i);

                                          }

                                         

                                   }

                            }

              ).start();

             

              for(int i=1;i<=50;i++){

                     business.main(i);

              }

             

       }

 

}

 class Business {

         private boolean bShouldSub = true;

         public synchronized void sub(int i){

                while(!bShouldSub){

                       try {

                            this.wait();

                     }catch (InterruptedException e) {

                            //TODO Auto-generated catch block

                            e.printStackTrace();

                     }

                }

                     for(intj=1;j<=10;j++){

                            System.out.println("subthread sequence of " + j + ",loop of " + i);

                     }

                bShouldSub = false;

                this.notify();

         }

        

         public synchronized void main(int i){

                    while(bShouldSub){

                           try {

                                   this.wait();

                            }catch (InterruptedException e) {

                                   //TODO Auto-generated catch block

                                   e.printStackTrace();

                            }

                    }

                     for(intj=1;j<=100;j++){

                            System.out.println("mainthread sequence of " + j + ",loop of " + i);

                     }

                     bShouldSub = true;

                     this.notify();

         }

  }



public class TraditionalThreadCommunication {/** * @param args */public static void main(String[] args) {final Business business = new Business();new Thread(new Runnable() {@Overridepublic void run() {for(int i=1;i<=50;i++){business.sub(i);}}}).start();for(int i=1;i<=50;i++){business.main(i);}}}  class Business {  private boolean bShouldSub = true;  public synchronized void sub(int i){  while(!bShouldSub){  try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}  }for(int j=1;j<=10;j++){System.out.println("sub thread sequence of " + j + ",loop of " + i);}  bShouldSub = false;  this.notify();  }    public synchronized void main(int i){  while(bShouldSub){  try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}  }for(int j=1;j<=100;j++){System.out.println("main thread sequence of " + j + ",loop of " + i);}bShouldSub = true;this.notify();  }  }


0 0