多线程的练习----妖,等待唤醒,代码重构,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的随机性,有可能被多个线程分开执行.导致数据安全问题. ...
随机推荐
- 解决NDK开发中Eclipse报错“Unresolved inclusion jni.h”的最终方法
http://blog.csdn.net/zhubin215130/article/details/39347873
- eclipse提示servlet不存在 的解决办法
在以前的版本中,Tomcat的common/lib目录下有一个名为servlet-api.jar的包,把它拷贝至你的java安装目录下jre/lib/ext下就可以了. 如果是:tomcat6就在To ...
- eclipse插入自定义注释(含当前系统时间)
/** * @author ${user} * @description * ${tags} * @CreateDate ${date} ${time} * @modifyUser * @modify ...
- START167 AND BOOT167
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka10535.html C166: START167 AND BOO ...
- HDU1028 Ignatius and the Princess III 【母函数模板题】
Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- Html5游戏开发开始前的一些数学基础
计算一个向量的值 var vectorMagnitude = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2)); 单位向量 var ve ...
- cookie标准话
php设置cookie setcookie( * * ,'/'); setcookie( * * ,'/'); //清除cookie setcookie("loginname",' ...
- Android自定义长按事件
Android系统自带了长按事件,setOnLongClickListener即可监听.但是有时候,你不希望用系统的长按事件,比如当希望长按的时间更长一点的时候.这时候就需要自己来定义这个长按事件了. ...
- javascript complete, onload
1.complete 属性可返回浏览器是否已完成对图像的加载 <html> <head> <script type="text/javascript" ...
- 如何为Linux安装Go语言
导读 Go 语言又称为 golang, 是由 Google 最初开发的一种开源编程语言,其在设计时就遵循了简单.安全和速度的 3 大原则.Go 语言具有多种调试.测试.分析和代码审查工具,如今 Go ...