博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
黑马程序猿——12,多线程(2)
阅读量:5336 次
发布时间:2019-06-15

本文共 23968 字,大约阅读时间需要 79 分钟。

------<ahref="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

              黑马程序猿——12,多线程(2)

 

//线程之间的通信//就是多个线程操作同一个资源,操作动作不同//举一个样例:一堆资源(名字,性别),一个线程输入,一个线程输出打印 class  Person{         String  name;         String  sex;} class   Shuru  implements  Runnable            {     private  Person  p;           Shuru( Person p   )           {               this.p=p;           }           public  void  run()           {                     int x= 0;                     while(true)//特别说明:由于 while (true)这句话的关系。最后要按Ctrl+c按键才停下虚拟机,否则会耗费非常多资源)                             {            if(x==0)                              {               p.name="张三";                          p.sex="男性";                              }                              else                              {               p.name="李四";                          p.sex="女性";                              }                              x=(x+1)%2;                     }           }}class  Shuchu  implements  Runnable{           private Person  p;           Shuchu( Person  p   )           {               this.p=p;           }            public  void  run()           {               while(true)                     {                               System.out.println(p.name+"-----"+p.sex);                     }           } } class Xctx{         public  static  void  main(String[] args)         {                   Person  p=new Person();                    Shuru  b1=new Shuru(p);                   Shuchu  b2=new Shuchu(p);                    Thread  c1=new Thread(b1);                   Thread  c2=new Thread(b2);                    c1.start();             c2.start();                   System.out.println("HelloWorld!");         }} /*依照一般的思路。准确的打印应该是张三相应男性,李四相应女性的但是编译执行的结果例如以下。出了问题:Hello World!李四-----男性李四-----男性李四-----女性李四-----男性张三-----女性张三-----女性李四-----男性李四-----男性张三-----男性张三-----女性张三-----男性张三-----男性李四-----男性张三-----男性李四-----女性李四-----男性张三-----男性李四-----女性张三-----女性李四-----女性李四-----男性  出问题的解决办法是:输入线程在输入信息的同一时候输出线程也在打印,那么非常有可能在输入信息输入到一半的时候。就被输出线程打印出去了。那么打印出去的就是部分更新数据部分旧数据,这就相应不上了*/

——————分析——————

//为了解决这样的问题,我们还是能够用同步代码块来解决/*原理就是输入线程与输出线程都是对同一个对象操作。仅仅只是操作过程不一样那么使用同步代码块,让两个使用同一个锁,这样就限制了在某一个时刻仅仅能够有一个线程对对象进行操作等这个线程操作完之后下一个线程才干够对对象进行操作确保了打印出来的对象信息的更新是完整*/ class  Person{         String  name;         String  sex;         static  Object obj=new Object();} class   Shuru  implements Runnable            {     private  Person  p;           Shuru( Person p   )           {               this.p=p;           }           public  void run()           {                     int x= 0;                     while(true)//特别说明:由于 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机。否则会耗费非常多资源)                             {                              synchronized(Person.obj)//用的锁是obj                              {                if(x==0)                                {                  p.name="张三";                             p.sex="男性";                                }                                else                                {                   p.name="李四";                              p.sex="女性";                                }                                x=(x+1)%2;                             }                     }           }  }class   Shuchu  implements  Runnable{           private  Person   p;           Shuchu( Person  p   )           {               this.p=p;           }            public void run()           {               while(true)                     {                               synchronized(Person.obj)//用的锁是obj                              {                             System.out.println(p.name+"-----"+p.sex);                              }                     }           } } class  Xctx2{         public  static  void  main(String[] args)         {                   Person  p=new Person();                    Shuru  b1=new Shuru(p);                   Shuchu  b2=new Shuchu(p);                    Thread  c1=new Thread(b1);                   Thread  c2=new Thread(b2);                    c1.start();             c2.start();                   System.out.println("HelloWorld!");         }}

——————分析——————

//线程通信中的等待唤醒机制的样例 /*等待唤醒机制,简单的说法就是用一个标示(通常是Boolean型的变量)true标记输入线程操作,而false标记输出线程操作输入线程操作时候,输出线程冻结状态输出线程操作时候。输入线程冻结状态这样来保证输出结果的准确性这就须要用到wait()和notify()  或者是notifyAll()*/class  Person{         String  name;         String  sex;         static  Object obj=new Object();         boolean  bs=true;//设定一个标示} class   Shuru  implements Runnable            {     private  Person  p;           Shuru( Person p   )           {               this.p=p;//接收一个Person类的对象,就指向该对象。该写法更加方便           }           public  void  run()           {                     int x= 0;                     while(true)//特别说明:由于 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机。否则会耗费非常多资源)                             {                              synchronized(Person.obj)//用的锁是obj                              {                if(!p.bs)                                       {                                               try{Person.obj.wait();}catch(Exception e){}                                       }                                               //wait()方法能够冻结线程,该方法是定义在Object类的                                               /*                               这里为什么不直接用wait()呢?                               由于wait()方法会抛出一个异常所以要用try...catch                               为什么这里还要在wait前面加上Person.obj这个锁呢?                               由于这样的写法:锁.wait();   -----表示持有该锁的线程要陷入沉睡。                               也是由于这个原因,wait()方法必须在同步中才干够用,而notify()                                和notifyAll()也是由于以上原因在同步中才干够用。                               其写法也是:  锁.notify();或者是  锁.notifyAll();                                                                 */                if(x==0)                                {                  p.name="张三";                             p.sex="男性";                                }                                else                                {                  p.name="李四";                              p.sex="女性";                                }                                x=(x+1)%2;                Person.obj.notify();                                     /*                                     陷入沉睡的线程都会被扔进线程池                                     notify()方法功能是唤醒在在线程池中头一个沉睡的线程                                     而notifyAll()方法则是唤醒全部沉睡的线程                                     */                 p.bs=false;                             }                     }           }  }class   Shuchu  implements  Runnable{           private  Person   p;           Shuchu( Person  p   )           {               this.p=p;           }            public  void  run()           {               while(true)                     {                               synchronized(Person.obj)//用的锁是obj                              {                                       if(p.bs)                                       {                                                 try{Person.obj.wait();} catch(Exception e){}                                       }                                                                                        System.out.println(p.name+"-----"+p.sex);                                       Person.obj.notify();                  p.bs=true;                              }                     }           } } class Xctx3{         public  static void main(String[] args)         {                   Person  p=new Person();                    Shuru  b1=new Shuru(p);                   Shuchu  b2=new Shuchu(p);                    Thread  c1=new Thread(b1);                   Thread  c2=new Thread(b2);                    c1.start();             c2.start();                   System.out.println("HelloWorld!");         }}/*以上程序编译执行结果是:Hello World!张三-----男性李四-----女性张三-----男性李四-----女性张三-----男性李四-----女性张三-----男性李四-----女性张三-----男性李四-----女性张三-----男性李四-----女性张三-----男性李四-----女性 */
 

补充:对于非静态的synchronized方法,其锁默觉得this

           对于静态的synchronized方法。其锁默认:为该方法所在类的类名.class     

         对于同步代码块,其锁就是括号内的东西。

——————切割线————————

//下面是代码优化之后的程序,更加简洁明了class  Person{         private  String  name;         private  String  sex;                 private  boolean  bs=true;//设定一个标示         public  synchronized  void  set( String name,String  sex   )//写入资料的方法         {                   if(!bs)                   {                                   try{this.wait();}catch(Exception e){}                   }                                                  this.name=name;                    this.sex=sex;                    bs=false;                     this.notify();         }         public  synchronized  void  out()//打印资料的方法         {         if(bs)                   {                                   try{this.wait();}catch(Exception e){}                   }            System.out.println("输出的是----"+name+"---"+sex);                    bs=true;                    this.notify();         }} class   Shuru  implements  Runnable            {     private  Person  p;           Shuru( Person p   )           {               this.p=p;           }           public  void  run()           {                     int x= 0;                     while(true)//特别说明:由于 while (true)这句话的关系,最后要按Ctrl+c按键才停下虚拟机。否则会耗费非常多资源)                             {                         if(x==0)                   p.set("张三","男性");                                else                    p.set("李四","女性");                                                                   x=(x+1)%2;                                                }           }  }class  Shuchu  implements  Runnable{           private Person  p;           Shuchu( Person  p   )           {               this.p=p;           }            public void run()           {               while(true)                     {                            p.out();                     }           } } class  Xctx4{         public  static  void  main(String[] args)         {                   Person  p=new Person();                    newThread(new Shuru(p)).start();             new Thread(new Shuchu(p)).start();                    System.out.println("HelloWorld!");/*                   Shuru  b1=new Shuru(p);                   Shuchu  b2=new Shuchu(p);                    Thread  c1=new Thread(b1);                   Thread  c2=new Thread(b2);                    c1.start();             c2.start();                   System.out.println("HelloWorld!");*/         }}

————————切割线——————

/*多线程的常见生活样例有多个生产者生产食品,有多个消费者消化食品每生产一个食品就消费一个食品*/ class  Shipin{         private  int  sp=0;         private   boolean   f=true;         public  synchronized  void  shengchang(  )         {                   while(true)                   {                            while(f==false)//注意这里用的是while所以每次线程从冻结状态醒来都要检查一次f是否是false                       try{this.wait();} catch(Exception e){}        sp++;              System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp);                                      f=false;                    this.notifyAll();                    /*                       这里用notifyAll()方法就是为了让全部沉睡的线程醒来          既唤醒了生产者又唤醒了消费者          此时假设f=true那么因为之前的while作用。消费者即使是得到权限(锁)也不能运行仅仅能冻结,所以仅仅有一个生产者能够得到权限运行。         此时假设是f=false那么因为之前的while作用,生产者即使是得到权限(锁)也不能运行仅仅能冻结所以仅仅有一个消费者能够得到权限运行。                    */                   }                           }         public  synchronized  void  xiaofei(   )         {                   while(true)                   {                     while(f==true)                       try{this.wait();} catch(Exception e){}                  System.out.println("消费者"+Thread.currentThread().getName()+"----"+sp);                                        f=true;                      this.notifyAll();                   }         }}class  Shengchangzhe  implements  Runnable{         private  Shipin   a ;         Shengchangzhe(Shipin   a)         {             this.a=a;         }   public void run()         {              a.shengchang();              }} class  Xiaofeizhe  implements  Runnable{   private  Shipin   a ;         Xiaofeizhe(Shipin   a)         {             this.a=a;         }   public  void run()         {              a.xiaofei();              }}class   Xctx5{         public  static  void  main(String[] args)         {                   Shipin  a=new Shipin();                    Shengchangzhe  b1=new Shengchangzhe(a);                   Shengchangzhe  b2=new Shengchangzhe(a);                   Xiaofeizhe     b3=new Xiaofeizhe(a);       Xiaofeizhe     b4=newXiaofeizhe(a);                    Thread  t1=new Thread(b1);                Thread  t2=new Thread(b2);             Thread t3=new Thread(b3);                   Thread  t4=new Thread(b4);        t1.start();       t2.start();             t3.start();             t4.start();                   System.out.println("HelloWorld!");         }}/*以上程序编译运行结果例如以下:生产者Thread-0----1Hello World!消费者Thread-3----1生产者Thread-1----2消费者Thread-2----2生产者Thread-0----3消费者Thread-3----3生产者Thread-1----4消费者Thread-2----4生产者Thread-0----5消费者Thread-3----5生产者Thread-1----6消费者Thread-2----6生产者Thread-0----7消费者Thread-3----7生产者Thread-1----8消费者Thread-2----8生产者Thread-0----9消费者Thread-3----9生产者Thread-1----10消费者Thread-2----10生产者Thread-0----11消费者Thread-3----11生产者Thread-1----12消费者Thread-2----12生产者Thread-0----13消费者Thread-3----13生产者Thread-1----14消费者Thread-2----14生产者Thread-0----15消费者Thread-3----15生产者Thread-1----16消费者Thread-2----16生产者Thread-0----17消费者Thread-3----17生产者Thread-1----18消费者Thread-2----18生产者Thread-0----19消费者Thread-3----19生产者Thread-1----20消费者Thread-2----20生产者Thread-0----21消费者Thread-3----21生产者Thread-1----22消费者Thread-2----22生产者Thread-0----23消费者Thread-3----23生产者Thread-1----24消费者Thread-2----24生产者Thread-0----25消费者Thread-3----25生产者Thread-1----26消费者Thread-2----26生产者Thread-0----27消费者Thread-3----27生产者Thread-1----28消费者Thread-2----28生产者Thread-0----29消费者Thread-3----29生产者Thread-1----30消费者Thread-2----30生产者Thread-0----31*/

——————切割线————

 

//另外一个是jdk1.5版本号升级后的情况:import java.util.concurrent.locks.*;//这个导入的是后面须要用到的类 /*随着jdk1.5版本号的升级,一些新的功能也被增加。更加的方便使用者就拿多线程通信的生产者消费者样例来说*/ class   Xctx6{         public  static  void  main(String[] args)         {                   Shipin  a=new Shipin();                    Shengchangzhe  b1=new Shengchangzhe(a);                                   Xiaofeizhe     b2=new Xiaofeizhe(a);                         Thread  t1=new Thread(b1);                   Thread  t2=new Thread(b1);                   Thread t3=new Thread(b2);                   Thread  t4=new Thread(b2);              t1.start();             t2.start();             t3.start();             t4.start();                   System.out.println("HelloWorld!");         }}class   Shipin{         private  int sp=0;         private  boolean  f=true;         private  Lock   lock=new   ReentrantLock();//将锁作为一个对象了    private  Condition  pro= lock.newCondition();   private  Condition  con= lock.newCondition();   /*             Condition将Object监视器(锁)的方法(wait,notify。notifyAll)分解成不同的对象,                   这是为了便于与Lock组合使用。       Lock取代synchronized方法和语句的使用(同步函数和同步代码块)                   Condition替代了Object监视器(锁)的方法的使用。                   Condition实例是绑定在锁上的。一个Lock实例要获得Condition实例就要调用newCondition方法。

*/ public void shengchang() throws InterruptedException { lock.lock(); try { while(f==false) pro.await();//生产者线程陷入冻结 //这个句式会抛出一个InterruptedException异常 sp++; System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp); f=false; con.signal();//只唤醒消费者线程 } finally { lock.unlock();//释放锁 } /* 这里是所以要使用try...finally句型是由于确保 一定要运行 lock.unlock();也是由于前面的pro.await();会向外抛出 一个异常,假设没有这个句型程序就会跳出去而没有 运行lock.unlock();这种话线程就没有释放锁 */ } public void xiaofei() throws InterruptedException { lock.lock(); try { while(f==true) con.await();//消费者线程陷入冻结 System.out.println("消费者"+Thread.currentThread().getName()+"----"+sp); f=true; pro.signal();//唤醒生产者线程 } finally { lock.unlock(); } } } class Shengchangzhe implements Runnable { private Shipin a ; Shengchangzhe(Shipin a) { this.a=a; } public void run() { while(true) { try{a.shengchang();} catch(Exception e){} } } } class Xiaofeizhe implements Runnable { private Shipin a ; Xiaofeizhe(Shipin a) { this.a=a; } public void run() { while(true) { try{a.xiaofei();} catch(Exception e){} } } }

/*

对前面的样例做了一个改进:

有生产者,检查者。消费者

先要由生产者生产食品,

然后由检查者检測食品。

最后由消费者消化食品。

*/

import java.util.concurrent.locks.*; class  Xctx7{         public  static  void  main(String[] args)         {                   Shipin  a=new Shipin();                    Shengchangzhe  b1=new Shengchangzhe(a);                                   Xiaofeizhe     b2=new Xiaofeizhe(a);                   Jiancezhe      b3=new Jiancezhe(a);                    Thread  t1=new Thread(b1);                   Thread  t2=new Thread(b1);                   Thread t3=new Thread(b2);                   Thread  t4=new Thread(b2);                   Thread t5=new Thread(b3);                   Thread  t6=new Thread(b3);               t1.start();             t2.start();             t3.start();             t4.start();             t5.start();             t6.start();                   System.out.println("HelloWorld!");         }}class   Shipin{         private  int sp=0;         private  int  f=1;         private  Lock lock=new ReentrantLock();//将锁作为一个对象了    private  Condition  pro= lock.newCondition();   private  Condition  con= lock.newCondition();   private  Condition  jc = lock.newCondition();          public    void shengchang() throws InterruptedException          {                   lock.lock();                   try                   {                    while(f!=1)                             {                             pro.await();//生产者线程陷入冻结                             }                            sp++;              System.out.println("生产者"+Thread.currentThread().getName()+"----"+sp);                                      f=2;                   jc.signal();//唤醒检測者线程                   }                   finally                   {                        lock.unlock();//释放锁                   }                                  }         public  void  xiaofei() throws   InterruptedException          {                   lock.lock();                   try                   {                      while(f!=3)                            {                       con.await();//消费者线程陷入冻结                            }                                           System.out.println("消费者"+Thread.currentThread().getName()+"----------"+sp);                      f=1;                      pro.signal();//唤醒生产者线程                   }                   finally                   {                     lock.unlock();                   }         }   public  void  jiance() throws  InterruptedException  //检測方法         {                   lock.lock();                   try                   {                      while(f!=2)                            {                       jc.await();//检測者线程陷入冻结                                                       }                System.out.println("检測者"+Thread.currentThread().getName()+"-------"+sp);                      f=3;                      con.signal();//唤醒消费者线程                   }                   finally                   {                     lock.unlock();                   }         } }class   Shengchangzhe  implements  Runnable{         privateShipin   a ;         Shengchangzhe(Shipin   a)         {             this.a=a;         }   public   void   run()         {                   while(true)                   {                     try{a.shengchang();}                     catch(Exception e){}                   }         }} class   Xiaofeizhe  implements   Runnable{   private   Shipin   a ;         Xiaofeizhe(Shipin   a)         {             this.a=a;         }   public  void  run()         {                   while(true)                   {                     try{a.xiaofei();}                     catch(Exception e){}                   }         }}class   Jiancezhe  implements Runnable{   private   Shipin   a ;         Jiancezhe(Shipin   a)         {             this.a=a;         }   public   void   run()         {                   while(true)                   {                     try{a.jiance();}                     catch(Exception e){}                   }         }}/*以上的代码编译执行结果例如以下:生产者Thread-0----1Hello World!检測者Thread-4-------1消费者Thread-3----------1生产者Thread-0----2检測者Thread-5-------2消费者Thread-3----------2生产者Thread-1----3检測者Thread-5-------3消费者Thread-2----------3生产者Thread-0----4检測者Thread-4-------4消费者Thread-3----------4生产者Thread-1----5检測者Thread-5-------5消费者Thread-2----------5生产者Thread-0----6检測者Thread-4-------6消费者Thread-3----------6生产者Thread-1----7检測者Thread-5-------7消费者Thread-2----------7生产者Thread-0----8检測者Thread-4-------8消费者Thread-3----------8生产者Thread-1----9检測者Thread-5-------9消费者Thread-2----------9生产者Thread-0----10检測者Thread-4-------10消费者Thread-3----------10生产者Thread-1----11检測者Thread-5-------11消费者Thread-2----------11生产者Thread-0----12检測者Thread-4-------12消费者Thread-3----------12生产者Thread-1----13检測者Thread-5-------13消费者Thread-2----------13生产者Thread-0----14检測者Thread-4-------14消费者Thread-3----------14生产者Thread-1----15检測者Thread-5-------15消费者Thread-2----------15生产者Thread-0----16检測者Thread-4-------16消费者Thread-3----------16生产者Thread-1----17检測者Thread-5-------17消费者Thread-2----------17生产者Thread-0----18检測者Thread-4-------18消费者Thread-3----------18生产者Thread-1----19检測者Thread-5-------19消费者Thread-2----------19生产者Thread-0----20检測者Thread-4-------20消费者Thread-3----------20生产者Thread-1----21检測者Thread-5-------21消费者Thread-2----------21生产者Thread-0----22检測者Thread-4-------22消费者Thread-3----------22生产者Thread-1----23检測者Thread-5-------23消费者Thread-2----------23生产者Thread-0----24检測者Thread-4-------24消费者Thread-3----------24生产者Thread-1----25检測者Thread-5-------25消费者Thread-2----------25生产者Thread-0----26检測者Thread-4-------26消费者Thread-3----------26生产者Thread-1----27检測者Thread-5-------27消费者Thread-2----------27生产者Thread-0----28检測者Thread-4-------28消费者Thread-3----------28生产者Thread-1----29检測者Thread-5-------29消费者Thread-2----------29生产者Thread-0----30检測者Thread-4-------30消费者Thread-3----------30生产者Thread-1----31检測者Thread-5-------31消费者Thread-2----------31生产者Thread-0----32检測者Thread-4-------32消费者Thread-3----------32生产者Thread-1----33检測者Thread-5-------33消费者Thread-2----------33生产者Thread-0----34检測者Thread-4-------34消费者Thread-3----------34生产者Thread-1----35检測者Thread-5-------35消费者Thread-2----------35生产者Thread-0----36检測者Thread-4-------36消费者Thread-3----------36生产者Thread-1----37检測者Thread-5-------37消费者Thread-2----------37生产者Thread-0----38检測者Thread-4-------38消费者Thread-3----------38生产者Thread-1----39检測者Thread-5-------39消费者Thread-2----------39生产者Thread-0----40检測者Thread-4-------40消费者Thread-3----------40生产者Thread-1----41检測者Thread-5-------41消费者Thread-2----------41生产者Thread-0----42检測者Thread-4-------42消费者Thread-3----------42生产者Thread-1----43检測者Thread-5-------43消费者Thread-2----------43生产者Thread-0----44检測者Thread-4-------44消费者Thread-3----------44生产者Thread-1----45检測者Thread-5-------45消费者Thread-2----------45生产者Thread-0----46检測者Thread-4-------46消费者Thread-3----------46生产者Thread-1----47检測者Thread-5-------47消费者Thread-2----------47生产者Thread-0----48检測者Thread-4-------48消费者Thread-3----------48生产者Thread-1----49检測者Thread-5-------49消费者Thread-2----------49生产者Thread-0----50检測者Thread-4-------50消费者Thread-3----------50生产者Thread-1----51检測者Thread-5-------51消费者Thread-2----------51生产者Thread-0----52检測者Thread-4-------52消费者Thread-3----------52生产者Thread-1----53检測者Thread-5-------53消费者Thread-2----------53生产者Thread-0----54检測者Thread-4-------54消费者Thread-3----------54生产者Thread-1----55检測者Thread-5-------55消费者Thread-2----------55生产者Thread-0----56检測者Thread-4-------56消费者Thread-3----------56生产者Thread-1----57检測者Thread-5-------57消费者Thread-2----------57生产者Thread-0----58检測者Thread-4-------58消费者Thread-3----------58生产者Thread-1----59检測者Thread-5-------59消费者Thread-2----------59生产者Thread-0----60检測者Thread-4-------60消费者Thread-3----------60生产者Thread-1----61检測者Thread-5-------61消费者Thread-2----------61生产者Thread-0----62检測者Thread-4-------62消费者Thread-3----------62生产者Thread-1----63检測者Thread-5-------63消费者Thread-2----------63*/

转载于:https://www.cnblogs.com/llguanli/p/6738252.html

你可能感兴趣的文章
JavaScript中的BOM和DOM
查看>>
注册表操作
查看>>
360浏览器兼容模式 不能$.post (不是a 连接 onclick的问题!!)
查看>>
Yii安装使用教程(转)
查看>>
Java四种引用包括强引用,软引用,弱引用,虚引用。
查看>>
spring注入Properties
查看>>
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
查看>>
【BZOJ-2295】我爱你啊 暴力
查看>>
【BZOJ-1055】玩具取名 区间DP
查看>>
Bit Twiddling Hacks
查看>>
Windwos中的线程同步
查看>>
LeetCode : Reverse Vowels of a String
查看>>
时间戳与日期的相互转换
查看>>
jmeter(五)创建web测试计划
查看>>
python基本数据类型
查看>>
1305: [CQOI2009]dance跳舞 - BZOJ
查看>>
关于TDD的思考
查看>>
Cocos2d-x学习之windows 7 android环境搭建
查看>>
将html代码中的大写标签转换成小写标签
查看>>
jmeter多线程组间的参数传递
查看>>