线程通讯
来源:互联网 发布:eva625软件下载 编辑:程序博客网 时间:2024/06/04 18:39
线程通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。
解决安全问题
class Res{String name;String sex;}class Input implements Runnable{private Res r;Input(Res r){this.r = r;}public void run(){int x = 0;while(true){if(x == 0){r.name = "mike";r.sex = "man";}else{r.name = "丽丽";r.sex = "女";}x = (x + 1)%2;}}}class Output implements Runnable{private Res r;Output(Res r){this.r = r;}public void run(){while(true){System.out.println(r.name+"..."+r.sex);}}}class InputOutputDemo{public static void main(String[] args){Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t1 = new Thread(in);Thread t2 = new Thread(out);t1.start();t2.start();}}
运行结果会出现这种情况:
这是因为:假如原先输入中的姓名、性别分别是丽丽、女。再一次输入的时候,只添入了姓名“mike”,还没添入性别的时候,执行权被输出线程抢走,输出“mike...女”的情况。
用同步来解决:
class Res{String name;String sex;}class Input implements Runnable{private Res r;Object obj = new Object();Input(<span style="color:#333333;">Res r</span>){this.r = r;}public void run(){int x = 0;while(true){synchronized(<span style="color:#cc33cc;">obj</span>){if(x == 0){r.name = "mike";r.sex = "man";}else{r.name = "丽丽";r.sex = "女";}x = (x + 1)%2;}}}}class Output implements Runnable{private Res r;Object obj = new Object();Output(Res r){this.r = r;}public void run(){while(true){synchronized(<span style="color:#cc33cc;">obj</span>){System.out.println(r.name+"..."+r.sex);}}}}class InputOutputDemo{public static void main(String[] args){Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t1 = new Thread(in);Thread t2 = new Thread(out);t1.start();t2.start();}}
输出结果:
加了锁之后仍然出现问题,要看看是否满足那两个准则。
1.是否是两个或多个线程。
2.是否是同一个锁。
显然第一个条件满足。但是第二个条件不满足。因为Object类创建的是两个对象。
解决方法:可以用 类名:class,内存中有四个唯一的类,所以锁可以是Res.class,Input.class,Output.clss,InputOutputDemo.class。因为资源r也是唯一的,所以锁也可以是r。
等待唤醒机制
还是上一个程序,它的打印结果是“mike...man”成片出现,“丽丽...女”成片出现。这种情况的原因是输入线程抢到执行权后,它会不止一次的输入,不断更新当前的输入结果。而当输出线程抢到CPU执行权后,它也会不止一次的输出,于是就出现了上述情形。
我们要的结果应该是输入一次,紧接着输出一次。这就用到了等待唤醒机制。
<pre name="code" class="java">class Res{String name;String sex;boolean flag = false;public <span style="color:#66ffff;">synchronized</span> void set(String name,String sex){if(flag)try{<span style="color:#ff0000;">this.wait()</span>;}catch(Exception e){}this.name = name;this.sex = sex;flag = true;<span style="color:#ff0000;">this.notify()</span>;}public <span style="color:#66ffff;">synchronized</span> void out(){if(!flag)try{<span style="color:#33cc00;">this.wait()</span>;}catch(Exception e){}System.out.println(r.name+"..."+r.sex);flag = false;<span style="color:#33cc00;">this.notify();</span>}}class Input implements Runnable{private Res r;Input(Res r){this.r = r;}public void run(){int x = 0;while(true){if(x == 0){r.set("mike","man");}else{r.set("丽丽","女");}x = (x + 1)%2;}}}}class Output implements Runnable{private Res r;Output(Res r){this.r = r;}public void run(){while(true){r.out();}}}class InputOutputDemo{public static void main(String[] args){Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t1 = new Thread(in);Thread t2 = new Thread(out);t1.start();t2.start();}}
wait(),notify(),notifyAll() 都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只要同步中才具有锁。
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步线程时,都必须要标识它们所操作线程持有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以被不同锁上的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
- 线程通讯
- 线程通讯
- 线程同步和线程通讯
- 线程同步和线程通讯
- 线程间通讯
- 线程间通讯--VC
- 线程间通讯
- linux进程线程通讯
- 线程间通讯
- 线程间通讯方法
- 多进程/线程通讯
- 四. 线程间通讯
- 线程间通讯
- 线程间通讯
- VC线程间通讯
- java线程通讯
- 线程间通讯
- android 线程间通讯
- 自定义tabbar
- Linux编程学习之Posix消息队列
- Android中的JSON详细总结
- mysql性能监控指标及分析
- java中最常用的100个类
- 线程通讯
- OpenGL--二次几何体
- visual tracking------object tracking && video tracking
- couchbase failover 集群故障自动转移方案研究!
- IOS计算缓存大小
- Java 基础 第四天
- leetcode 日经贴,Cpp code -Count Primes
- Linux 高可用(HA)集群之Corosync详解
- 我的IO漫谈2