zoukankan      html  css  js  c++  java
  • 多线程2--毕向东基础视频教程学习笔记

    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         else
    26 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 Runnable
    39 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 InputOutputDemo
    56 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 }
    View Code

     

    运行:

    出现了错误的输出。

     

    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         else
    30         {
    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 Runnable
    46 {
    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 InputOutputDemo
    69 {
    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 }
    View Code

    运行:

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

     

    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 Runnable
    10 {
    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         else
    33         {
    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 Runnable
    53 {
    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 InputOutputDemo
    81 {
    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 }
    View Code

     

    运行:

     

    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 Runnable
    32 {
    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            else
    50          {
    51             r.set("黎黎","女女女");
    52             
    53          }
    54         x=(x+1)%2;
    55         }
    56     
    57 
    58     }
    59 }
    60 class Output implements Runnable
    61 {
    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 InputOutputDemo
    78 {
    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 }
    View Code

     

    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 Runnable
    32 {
    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 Runnable
    47 {
    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 ProducerConsumerDemo
    62 {
    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 }
    View Code

    运行:

     

  • 相关阅读:
    super返回不过来
    对象与内存控制
    java数组学习
    careercup-递归和动态规划 9.8
    careercup-递归和动态规划 9.7
    careercup-递归和动态规划 9.6
    careercup-递归和动态规划 9.5
    careercup-递归和动态规划 9.4
    careercup-递归和动态规划 9.3
    careercup-递归和动态规划 9.2
  • 原文地址:https://www.cnblogs.com/wsw-tcsygrwfqd/p/5005911.html
Copyright © 2011-2022 走看看