多线程的练习----妖,等待唤醒,代码重构,lock到condition
1 需求
资源有姓名和性别。
两个线程,
一个负责给姓名和性别赋值,
一个负责获取姓名和性别的值。
要求1,运行一下,解决程序的 "妖"的问题。
要求2,实现正确数据的间隔输出 如
张飞--男
rose--女女女
张飞--男
rose--女女女
要求3,对代码进行重构。
将name,sex私有化,资源类提供对其访问的方法。
要求4,将程序改成JDK1.5的Lock Condition接口。
-------------------------------------
2 妖的出现和解决
原代码:
//描述资源。
class Resource
{
String name;
String sex;
}
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
{
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
}
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{ System.out.println(r.name+"....."+r.sex);
}
}
} class ThreadTest2
{
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(); }
}
测试结果: 会出现张飞.....女.或者是rose.....男,
分析原因:假如某个时刻,name=rose,sex=女,进入if中,进行了name=张三后就停止了,不进行了sex的赋值,进入打印,这是时的name=张三,sex=女;
解决方法:出现了安全问题.需要加入同步.详情请点击,
//描述资源。
class Resource
{
String name;
String sex;
}
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r) //加入同步
{
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
}
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r) //加入同步
{
System.out.println(r.name+"....."+r.sex);
}
}
}
} class ThreadTest2
{
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(); }
}
测试结果
-------------------------------------
3 等待唤醒
出现问题:由上面的结果可知,出现了大量的男或女,没有出现一男一女
解决问题:加入等待唤醒.输入后等待,唤醒输出,输出后,唤醒输入;一般要加入个标志
//描述资源。
class Resource
{
String name;
String sex;
//定义标记,
boolean flag = false; }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
try{r.wait();}catch(InterruptedException e){}//等待唤醒机制
if(x==0)
{
r.name = "张飞";
r.sex = "男";
}
else
{
r.name = "rose";
r.sex = "女女女女";
} r.flag = true;
r.notify(); //等待唤醒机制
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)//等待唤醒机制
try{r.wait();}catch(InterruptedException e){}
System.out.println(r.name+"....."+r.sex);
r.flag = false;
r.notify();//等待唤醒机制
}
}
}
} class ThreadTest2_2
{
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(); }
}
测试结果
-------------------------------------
4 代码重构
解决问题:将name,sex私有化,资源类提供对其访问的方法。这时加同步要放在共有资源里面
//描述资源。
class Resource
{
private String name; //
private String sex; //代码重构
//定义标记,
private boolean flag = false; //赋值功能。
public synchronized void set(String name,String sex)// //代码重构
{
if(flag)
try{this.wait();}catch(InterruptedException e){}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
} //获取值。
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(name+"------"+sex);
flag = false;
this.notify();
} }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("张飞","男");
}
else
{
r.set("rose","女女女女");
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
} class ThreadTest2_3
{
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(); }
}
-------------------------------------
5,将程序改成JDK1.5的Lock Condition接口
解决问题:Lock替换了 同步函数或者同步代码块。Condition替代了 监视器方法,将监视器方法从锁上分离出来,单独封装成Condition对象。
import java.util.concurrent.locks.*;
//描述资源。
class Resource
{
private String name;
private String sex; //程序改成JDK1.5的Lock Condition接口
//定义标记,
private boolean flag = false; //先创建锁对象。
private final Lock lock = new ReentrantLock();// //通过锁对象获取监视器对象。
private Condition con = lock.newCondition();// //赋值功能。
public void set(String name,String sex)
{
lock.lock();//
try{
if(flag)
try{con.await();}catch(InterruptedException e){}//
this.name = name;
this.sex = sex;
flag = true;
con.signal();//
}finally{
lock.unlock();//
}
} //获取值。
public void out()
{
lock.lock();//
try{
if(!flag)
try{con.await();}catch(InterruptedException e){}//
System.out.println(name+"------"+sex);
flag = false;
con.signal();//
}finally{
lock.unlock();//
}
} }
//赋值线程任务
class Input implements Runnable
{
private Resource r;
Input(Resource r)//任务一初始化就必须有要处理的资源。
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("张飞","男");
}
else
{
r.set("rose","女女女女");
}
x = (x+1)%2;//实现切换。
}
}
}
//获取值线程任务
class Output implements Runnable
{
private Resource r ;
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
} class ThreadTest2_4
{
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(); }
}
多线程的练习----妖,等待唤醒,代码重构,lock到condition的更多相关文章
- java-多线程的练习----妖,等待唤醒,代码重构,lock到condition
1 需求 资源有姓名和性别. 两个线程, 一个负责给姓名和性别赋值, 一个负责获取姓名和性别的值. 要求1,运行一下,解决程序的 "妖"的问题. 要求2,实现正确数据的 ...
- 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)
一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...
- Android-Java多线程通讯(生产者 消费者)&等待唤醒机制
多线程通讯:例如:有一个线程任务在run生产,还有一个线程任务在run消费: VIP尊贵的身份,生产者 消费者 方式,(精心生产制作一个超级无敌好吃的面包,卖给VIP尊贵的身份消费者)生产与消费 一对 ...
- Android-Java多线程通讯(生产者 消费者)&10条线程对-等待唤醒/机制的管理
上一篇博客 Android-Java多线程通讯(生产者 消费者)&等待唤醒机制 是两条线程(Thread-0 / Thread-1) 在被CPU随机切换执行: 而今天这篇博客是,在上一篇博客A ...
- java多线程中的生产者与消费者之等待唤醒机制@Version1.0
一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒: Object类中提供了三个方法: wait():等待 notify():唤醒单个线程 notify ...
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制
JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...
- Java多线程02(线程安全、线程同步、等待唤醒机制)
Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...
- Java多线程(二)同步与等待唤醒
1:数据安全问题 1.1:什么情况下会出现数据安全问题? 多个线程对同一个资源进行操作,并且操作资源的语句有多条.那么这个时候这些语句因为cpu的随机性,有可能被多个线程分开执行.导致数据安全问题. ...
随机推荐
- js 重载i
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- MHA高可用+VIP 集群故障转移(已测试成功)
服务器部署说明192.168.158.201 mha管理,mysql主服192.168.158.202 mha节点,mysql从服192.168.158.203 mha节点,mysql从服Man ...
- C#完成超酷的图像效果 (附demo)
如果您觉得C#制作的艺术字比较好玩, 但是还觉得没看够,不过瘾,那么我今天就让您一饱眼福, 看看C#如何制作的效果超酷的图像. (注: 我之前曾写过类似的文章, 但没有原理说明, 代码注释不够详细, ...
- 【转】Android开发实践:自定义带消息循环(Looper)的工作线程
http://ticktick.blog.51cto.com/823160/1565272 上一篇文章提到了Android系统的UI线程是一种带消息循环(Looper)机制的线程,同时Android也 ...
- NAT类型与穿透 及 STUN TURN 协议
STUN : Simple Traversal of User Datagram Protocol [UDP] Through Network Address Translators [NATs] S ...
- C# 程序员最常犯的 10 个错误
关于C# C#是达成微软公共语言运行库(CLR)的少数语言中的一种.达成CLR的语言可以受益于其带来的特性,如跨语言集成.异常处理.安全性增强.部件组合的简易模型以及调试和分析服务.作为现代的CLR语 ...
- JAVA学习第五十七课 — IO流(十一)
一.管道流 PipedInputStream 和 PipedOutPutStream 输入和输出能够直接进行连接.结合线程使用 管道流,顾名思义,写一个读一个.连成一个管子 API文档:管道输入流应该 ...
- Perl小知识点之排序sort
脚本这种东西,就是要常用,否则一段时间不用就生疏了,因此决定时时记一些小知识点,一来回顾一下,二来需要的时候可以迅速获得提示. Sort by number You could now write a ...
- Cocos2d-X内存管理研究<一>
http://hi.baidu.com/tzkt623/item/651ca7d7a0aff6e055347f67 半夜没事干,研究内核,作为我cocos2d-x的第一篇教程.cocos ...
- Golang学习 - errors 包
------------------------------------------------------------ Go 语言使用 error 类型来返回函数执行过程中遇到的错误,如果返回的 e ...