多线程2--毕向东基础视频教程学习笔记

来源:互联网 发布:中国经济数据网 编辑:程序博客网 时间:2024/04/30 10:46

转载地址:http://www.cnblogs.com/wsw-tcsygrwfqd/p/5005911.html


Day12多线程:

1.线程间通信-示例代码

2.线程间通信-解决安全问题

3.线程间通信-等待唤醒机制

4.线程间通信-代码优化

5.线程间通信-生产者消费者

 

 

1.线程间通信-示例代码

线程间通信:

其实就是多个线程在操作同一个资源,

但操作的动作不同。

示例代码:

复制代码
 1 class Res 2  2 { 3  3     String name; 4  4     String sex; 5  5      6  6 } 7  7 class Input implements Runnable 8  8 { 9  9     int x=0;10 10     private Res r;11 11     public Input(Res r)12 12     {13 13         this.r=r;14 14 15 15     }16 16     public void run()17 17     {18 18         while(true)19 19         {20 20             if(x==0)21 21         {22 22             r.name="Mike";23 23             r.sex="man";24 24         }25 25         else26 26         {27 27             r.name="黎黎";28 28             r.sex="女女女";29 29             30 30         }31 31         x=(x+1)%2;32 32 33 33         }34 34     35 35 36 36     }37 37 }38 38 class Output implements Runnable39 39 {40 40     private Res r;41 41     public Output(Res r)42 42     {43 43         this.r=r;44 44     }45 45     public void run()46 46     {47 47         while(true)48 48         {49 49             System.out.println(r.name+"---"+r.sex);50 50 51 51         }52 52 53 53     }54 54 }55 55 public class InputOutputDemo56 56 {57 57     public static void main(String[] args)58 58     {59 59         Res r=new Res();60 60         Output out=new Output(r);61 61         Input in=new Input(r);62 62 63 63         Thread t1=new Thread(in);64 64         Thread t2=new Thread(out);65 65 66 66         t1.start();67 67         t2.start();68 68     }69 69 }
复制代码

 

运行:

出现了错误的输出。

 

2.线程间通信-解决安全问题 

解决方法:

从两个方面考虑:

1.是否是多线程

2.是否用同一把锁。

改动后:

复制代码
 1 class Res 2 { 3     String name; 4     String sex; 5      6 } 7 class Input implements Runnable 8 { 9     int x=0;10     private Res r;11     public Input(Res r)12     {13         this.r=r;14 15     }16     public void run()17     {18         while(true)19         {20                         //添加同步代码块,使用对象r作为锁21 22             synchronized(r)23             {24                 if(x==0)25         {26             r.name="Mike";27             r.sex="man";28         }29         else30         {31             r.name="黎黎";32             r.sex="女女女";33             34         }35 36             }37             38         x=(x+1)%2;39 40         }41     42 43     }44 }45 class Output implements Runnable46 {47     private Res r;48     public Output(Res r)49     {50         this.r=r;51     }52     public void run()53     {54         while(true)55         {56                         //添加同步代码块,使用对象r作为锁57             synchronized(r)58             {59                 System.out.println(r.name+"---"+r.sex);60 61             }62             63 64         }65 66     }67 }68 public class InputOutputDemo69 {70     public static void main(String[] args)71     {72         Res r=new Res();73         Output out=new Output(r);74         Input in=new Input(r);75 76         Thread t1=new Thread(in);77         Thread t2=new Thread(out);78 79         t1.start();80         t2.start();81     }82 }
复制代码

运行:

不再有错误的输出,但是输出显示大片大片的男,大片大片的女。 

 

3.线程间通信-等待唤醒机制

要实现男女交替输出的效果,要用到wait和notify方法。

wait()

notify()

notifyAll()

都是用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中

只有同步才具有锁。

 

为什么这些操作线程的方法要定义在Object中呢?

因为这些方法在操作同步中的线程时,都必须标识它们所操作的线程持有的锁,

只有一个锁上的等待线程,可以被同一个锁上的notify唤醒。

不可以对不同锁上的线程进行唤醒。

 

也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,而可以被任意对象调用的方法定义在Object中。

修改后:

复制代码
 1 class Res 2 { 3     String name; 4     String sex; 5     //定义布尔型标志位 6     boolean flag=false; 7      8 } 9 class Input implements Runnable10 {11     int x=0;12     private Res r;13     public Input(Res r)14     {15         this.r=r;16 17     }18     public void run()19     {20         while(true)21         {22             synchronized(r)23             {24                 //判断标志位,是否等待25                 if(r.flag)26                 {try{r.wait();}catch(Exception e){}}27                 if(x==0)28         {29             r.name="Mike";30             r.sex="man";31         }32         else33         {34             r.name="黎黎";35             r.sex="女女女";36             37         }38         //改变flag值39         r.flag=true;40         //唤醒41         r.notify();42 43             }44             45         x=(x+1)%2;46 47         }48     49 50     }51 }52 class Output implements Runnable53 {54     private Res r;55     public Output(Res r)56     {57         this.r=r;58     }59     public void run()60     {61         while(true)62         {63             synchronized(r)64             {65                    //判断标志位,是否等待66                 if(!r.flag)67                     try{r.wait();}catch(Exception e){}68                 System.out.println(r.name+"---"+r.sex);69                         r.flag=false;70                         //唤醒71                         r.notify();72 73             }74             75 76         }77 78     }79 }80 public class InputOutputDemo81 {82     public static void main(String[] args)83     {84         Res r=new Res();85         Output out=new Output(r);86         Input in=new Input(r);87 88         Thread t1=new Thread(in);89         Thread t2=new Thread(out);90 91         t1.start();92         t2.start();93     }94 }
复制代码

 

运行:

 

4.线程间通信-代码优化

数据私有化,通过方法访问。

优化后代码:

复制代码
 1 class Res 2 { 3     //数据成员设置为私有 4     private String name; 5     private String sex; 6     //定义布尔型标志位 7     private boolean flag=false; 8      9     //定义set、get同步方法10     public synchronized void set(String name,String sex)11     {12         if(flag)13                 {try{this.wait();}catch(Exception e){}}14         this.name=name;15         this.sex=sex;16 17         flag=true;18         this.notify();19     }20     public synchronized void get()21     {22         if(!flag)23                 {try{this.wait();}catch(Exception e){}}24         System.out.println(name+"---"+sex);25 26         flag=false;27         this.notify();28     }29     30 }31 class Input implements Runnable32 {33     int x=0;34     private Res r;35     public Input(Res r)36     {37         this.r=r;38 39     }40     public void run()41     {42         while(true)43         {44                 if(x==0)45           {46             //调用set方法47             r.set("Mike","man");48           }49            else50          {51             r.set("黎黎","女女女");52             53          }54         x=(x+1)%2;55         }56     57 58     }59 }60 class Output implements Runnable61 {62     private Res r;63     public Output(Res r)64     {65         this.r=r;66     }67     public void run()68     {69         while(true)70         {71             //调用get方法72                 r.get();73         }74 75     }76 }77 public class InputOutputDemo78 {79     public static void main(String[] args)80     {81         Res r=new Res();82         //简化83         new Thread(new Input(r)).start();84         new Thread(new Output(r)).start();85 86     87     }88 }
复制代码

 

5.线程间通信-生产者消费者

当有多个生产者,多个消费者时,必须循环判断标记,以避免产生生产2个,只消费了一个或类似的情况;

并且使用notifyAll方法,以避免出现所有线程都在等待的情况。

复制代码
 1 class Resource 2 { 3     private String name; 4     private int count=1; 5     private boolean flag=false; 6  7     public synchronized void set(String _name) 8     { 9         while(flag)10         {11             try{wait();}catch(Exception e){}12         }13         name=_name+"--"+count++;14         System.out.println(Thread.currentThread().getName()+"--生产者"+name);15         flag=true;16         notifyAll();17 18     }19     public synchronized void get()20     {21         while(!flag)22         {23             try{wait();}catch(Exception e){}24         }25         System.out.println(Thread.currentThread().getName()+"--------消费者"+name);26         flag=false;27         notifyAll();28 29     }30 }31 class Producer implements Runnable32 {33     private Resource r=new Resource();34     public Producer(Resource r)35     {36         this.r=r;37     }38     public void run()39     {40         while(true)41         {42             r.set("商品");43         }44     }45 }46 class Consumer implements Runnable47 {48     private Resource r=new Resource();49     public Consumer(Resource r)50     {51         this.r=r;52     }53     public void run()54     {55         while(true)56         {57             r.get();58         }59     }60 }61 public class ProducerConsumerDemo62 {63     public static void main(String[] args)64     {65         Resource r=new Resource();66 67         Producer pro=new Producer(r);68         Consumer con=new Consumer(r);69 70         Thread t1=new Thread(pro);71         Thread t2=new Thread(pro);72         Thread t3=new Thread(con);73         Thread t4=new Thread(con);74 75         t1.start();76         t2.start();77         t3.start();78         t4.start();79 80     }81 }
复制代码

运行:

 


0 0
原创粉丝点击