博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程2--毕向东基础视频教程学习笔记
阅读量:5054 次
发布时间:2019-06-12

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

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 }
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         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 }
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 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 }
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 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 }
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 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 }
View Code

运行:

 

转载于:https://www.cnblogs.com/wsw-tcsygrwfqd/p/5005911.html

你可能感兴趣的文章
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
Centos6.4安装JDK
查看>>
【linux】重置fedora root密码
查看>>
pig自定义UDF
查看>>
Kubernetes 运维学习笔记
查看>>
Spark MLlib 之 Naive Bayes
查看>>
spring security 11种过滤器介绍
查看>>
学习网址
查看>>
前端表格插件datatables
查看>>
内部类
查看>>
树链剖分入门
查看>>
图解算法时间复杂度
查看>>
UI_搭建MVC
查看>>
一个样例看清楚JQuery子元素选择器children()和find()的差别
查看>>
代码实现导航栏分割线
查看>>
Windows Phone开发(7):当好总舵主 转:http://blog.csdn.net/tcjiaan/article/details/7281421...
查看>>
VS 2010打开设计器出现错误
查看>>
SQLServer 镜像功能完全实现
查看>>
Vue-详解设置路由导航的两种方法
查看>>