多线程间的通信问题
来源:互联网 发布:外贸进销存软件 编辑:程序博客网 时间:2024/06/06 01:16
一、线程间的通信
实例代码:
需求是:输入一个姓名和性别后,就输出一个姓名和性别
- class Resource
- {
- String name;
- String sex ;
- }
- class Input implements Runnable
- {
- Resource r;
- Input(Resource r)
- {
- this.r = r;
- }
- public void run()
- {
- int x = 0;
- while(true)
- {
- synchronized (r)
- {
- if(x==0)
- {
- r.name = "BLF";
- r.sex = "male";
- }
- else {
- r.name = "妮妮妮妮";
- r.sex = "female";
- }
- x = (++x)%2;
- }
- }
- }
- }
- class Output implements Runnable
- {
- Resource r;
- public Output(Resource r) {
- // TODO Auto-generated constructor stub
- this.r = r;
- }
- public void run()
- {
- while(true)
- {
- synchronized (r) //输入和输出都是应用同一个锁
- {
- System.out.println(r.name+"..."+r.sex);
- }
- }
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- Resource r = new Resource();//共享同一资源
- Input in = new Input(r);
- Output out = new Output(r);
- Thread t1 = new Thread(in);
- Thread t2 = new Thread(out);
- t1.start();
- t2.start();
- }
- }
上述代码虽然解决了,多线程处理同一资源问题,但是出现了一个问题就是,打印很多一个人名和性别后再打印另一个,无法实现交替输出,原因:输入线程获取执行权后,不会执行一次,输入姓名和性别,输入线程还拥有执行权,一直赋值,等到切换到输出执行权后,输出最后输入的姓名和性别,但是输出线程也不会只输出一次,一直输出,所以出现打印很多同一姓名和性别的问题
二、线程的等待/唤醒机制:
用一个boolean值判断是否有数据,有就不放,没有就放
输入线程执行时判断是否有数据,有,就释放执行权,再释放执行资格,进入冻结状态,输出线程执行,输出后boolean值置为false
- Input:
- if(flag)//有值
- wait();//当前冻结,切换输出线程
- flag = true;
- notify();
- Output:
- if(!flag)
- wait();
- flag = false;//flag置为假,输出完毕
- notify();//唤醒输入线程
等待/唤醒机制:
方法:
- 1.wait();//使线程进入冻结状态,CPU释放执行权和执行资格,被wait()的线程会被存储到线程池中
- 2.notify();//唤醒线程池中的任意的一个线程
- 3.notifyAll();//唤醒所有线程,使之处于运行状态或临时阻塞状态,总之,使其具备执行资格
这些方法必须定义在同步中,这些方法是用于操作线程状态的方法,所以必须明确在哪个锁上的线程
(wait()A锁的线程,只能用A锁的notify唤醒A锁的线程。)
了解:而wait()等方法是定义在Object类中的,这些方法是监视器的方法,而监视器呢,就可以理解为锁,控制哪个锁所属下的线程,而锁又可以是任意的,而所有的类都是继承于Object类的,所以wait()等类是定义在Object里
下述代码就解决了上述代码的问题,实现了输入输出线程的交替执行
- class Resource extends Object
- {
- String name;
- String sex ;
- boolean flag = false;
- }
- class Input implements Runnable
- {
- Resource r;
- Input(Resource r)
- {
- this.r = r;
- }
- public void run()
- {
- int x = 0;
- while(true)
- {
- synchronized (r)
- {
- if(r.flag)
- {
- try {
- r.wait();
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- if(x==0)
- {
- r.name = "BLF";
- r.sex = "male";
- }
- else {
- r.name = "妮妮妮妮";
- r.sex = "female";
- }
- r.flag = true;
- r.notify();
- x = (++x)%2;
- }
- }
- }
- }
- class Output implements Runnable
- {
- Resource r;
- public Output(Resource r) {
- // TODO Auto-generated constructor stub
- this.r = r;
- }
- public void run()
- {
- while(true)
- {
- synchronized (r)
- {
- if(!r.flag)
- {
- try {
- r.wait();
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- System.out.println(r.name+"..."+r.sex);
- r.flag = false;
- r.notify();
- }
- }
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- Resource r = new Resource();
- Input in = new Input(r);
- Output out = new Output(r);
- Thread t1 = new Thread(in);
- Thread t2 = new Thread(out);
- t1.start();
- t2.start();
- }
- }
三:等待唤醒机制代码优化
资源中的成员为了可控,应该为私有的,对外提供方法
所以同步的操作,就在Resource类中执行,应用同步函数
- class Resource extends Object
- {
- private String name;
- private String sex ;
- private boolean flag = false;
- public synchronized void set(String name,String sex)
- {
- // TODO Auto-generated constructor stub
- if(flag)
- {
- try {
- this.wait();
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- this.name = name;
- this.sex = sex;
- flag = true;
- this.notify();
- }
- public synchronized void out()
- {
- if(!flag)
- {
- try {
- this.wait();
- } catch (Exception e) {
- // TODO: handle exception
- }
- System.out.println(name+" : "+sex);
- flag = false;
- this.notify();
- }
- }
- }
- class Input implements Runnable
- {
- Resource r;
- Input(Resource r)
- {
- this.r = r;
- }
- public void run()
- {
- int x = 0;
- while(true)
- {
- if(x==0)
- {
- r.set("BLF", "male");
- }
- else
- {
- r.set("妮妮妮妮", "female");
- }
- x = (++x)%2;
- }
- }
- }
- class Output implements Runnable
- {
- Resource r;
- public Output(Resource r) {
- // TODO Auto-generated constructor stub
- this.r = r;
- }
- public void run()
- {
- while(true)
- {
- r.out();
- }
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- Resource r = new Resource();
- Input in = new Input(r);
- Output out = new Output(r);
- Thread t1 = new Thread(in);
- Thread t2 = new Thread(out);
- t1.start();
- t2.start();
- }
- }
0 0
- 多线程间的通信问题
- Java多线程间的通信问题扩展
- 多线程通信的注意问题
- 多线程间的通信
- 多线程间的通信问题之交替打印
- Linux 多线程通信方面的问题
- JAVA学习第二十六课(多线程(五))- 多线程间的通信问题
- 再论-多线程间的通信.
- Java多线程间的通信
- 关于多线程间通信的
- 【多线程】线程间的通信
- 多线程-线程间的通信
- Java多线程间的通信
- 多线程间通信的方法
- 9.多线程间的通信
- 多线程间通信 生产者消费者问题
- Java的多线程-线程间的通信
- 进击的多线程 --- 线程间的通信
- Android百度地图之自定义绘制功能
- 自从遇见你开始吧
- iOS: How To Make AutoLayout Work On A ScrollView
- Path和ClassPath的区别
- keystore信息的查看
- 多线程间的通信问题
- 常用Linux命令
- IOS7 TableView适配
- 在外部PHP文件中引用Magento代码
- 组合数学--错排问题
- 【原创】Zend Framework 2框架之MVC
- C语言实现大整数运算
- 关于AES256算法java端加密,ios端解密出现无法解密问题的解决方案
- 小波变换wavelet