黑马程序员技术交流社区
标题:
求解多线程中等待唤醒机制的问题
[打印本页]
作者:
周昭民
时间:
2014-2-5 13:41
标题:
求解多线程中等待唤醒机制的问题
/**
多线程等待唤醒机制
*/
package com.xiancheng;
class Res
{
private String name;
private String sex;
private boolean flag; //定义一个标记,用于判断有无信息,默认为false
synchronized void set(String name,String sex){
/* if(flag)
try{wait();}catch(Exception e){}
this.name=name;
this.sex=sex;
flag=true;
notify();
*/
if(!flag){ //当线程中并无信息时,则输入信息
this.name=name;
this.sex=sex;
flag=true; //输入完成,将标记置为true
notify(); //使另一线程进入唤醒状态
}else
try{wait();}catch(Exception e){} //有信息时则线程进入等待状态
}
synchronized void get(){
/*
if(!flag)
try{wait();}catch(Exception e){}
System.out.println(name+"的性别是"+sex);
flag=false;
notify();
*/
if(flag){ //当有信息时,打印信息
System.out.println(name+"的性别是"+sex);
flag=false; //打印完成后将标记置为false
notify(); //使另一线程进入唤醒状态
}else
try{wait();}catch(Exception e){} //无信息打印时线程进入等待状态
}
}
class Input implements Runnable //输入接口类
{
private Res r;
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0) //x为0时输入
r.set("小明","男"); //调用输入方法
else //否则输入
r.set("meimei","woman");//调用输入方法
x=(x+1)%2;
}
}
}
class Output implements Runnable //输出接口类
{
private Res r;
Output(Res r){
this.r=r;
}
public void run(){
while (true)
r.get(); //调用输出方法
}
}
class InputOutputDemo
{
public static void main(String args[]){
Res r=new Res();
Runnable r1=new Input(r); //创建接口对象1
Runnable r2=new Output(r); //创建接口对象2
Thread t1=new Thread(r1); //将对象1作为参数传入创建线程1
Thread t2=new Thread(r2); //将对象2作为参数传入创建线程2
t1.start(); //开启
t2.start(); //开启
}
}
复制代码
此代码的运行结果是输入一个打印一个,原本的程序是里面有两段注释的代码,根据毕老师的视频敲出来的,也没有问题。
但我最先敲的代码输出结果却不是和毕老师的一样,自己觉得好郁闷,我和老师的判断步骤就不一样了而已,结果就是有这么大的差异。求解
我的输出结果同一时间内全是一样,一段时间后又切到另一结果继续打印
作者:
周昭民
时间:
2014-2-8 15:17
代码我大概知道怎么改了,把else去掉就可以了。
只不过我还是不太懂得这里面的运行机制,虽然唤醒另一线程后本线程必须进入等待状态,所以else不加也可以。我只是加入else应该不是影响最终判断,下一次循环总会被判断到吧。只要flag标签发生了改变,它不是就会在下一次循环中执行了else里面的语句吗?
这几天都没人的吗?偌大的论坛,求解啊
作者:
天凌蓝
时间:
2014-3-4 14:29
室长来帮你解答;P,昭明,你看好啦,请看下面分析:lol。
class Res
{
private String name;
private String sex;
private boolean flag=false; //定义一个标记,用于判断有无信息,默认为false
synchronized void set(String name,String sex){
if(!flag){ //当线程中并无信息时,则输入信息
this.name=name;
this.sex=sex;
flag=true; //输入完成,将标记置为true
notify(); //使另一线程进入唤醒状态
}//else
try{wait();}catch(Exception e){} //有信息时则线程进入等待状态
}
/*
问题分析:
线程r1:
synchronized void set(String name,String sex){
if(!flag){ //当线程中并无信息时,则输入信息
this.name=name;
this.sex=sex;
flag=true; //输入完成,将标记置为true
notify(); //使另一线程进入唤醒状态
}else
try{wait();}catch(Exception e){} //有信息时则线程进入等待状态
}
线程r2:
synchronized void get(){
if(flag){ //当有信息时,打印信息
System.out.println(name+"的性别是"+sex);
flag=false; //打印完成后将标记置为false
notify(); //使另一线程进入唤醒状态
}else
try{wait();}catch(Exception e){} //无信息打印时线程进入等待状态
}
这两段代码你加了else之后再唤醒另一个线程,这样做事不行的。为什么?
因为假设r1线程获取到cpu执行权后,运行到if(!flag){}语句里面,此时r1线程改变了属性值后,
将flag标记为true,之后notify()唤醒了r2线程,但是因为你加了else,所以在if语句中,即你唤醒r2线程后,
你没有 【 直接 】将r1线程sleep。(如果没有直接sleep的话,会继续与r2争夺资源!!!)
而此时你又将线程r2唤醒,假设此时cpu的执行权还在线程r1手上,那么r2即使被唤醒,那么他也只能处于等待状态,
直到线程r1释放cpu执行权后,r2才能够被执行。
接着,当线程r2拿到cpu执行权后,r2线程运行到if(flag){ }语句中,此时r2获取属性值后,也将flag标记为false,
之后notify()唤醒了线程r1,【同样因为在if语句没有sleep自己】,所以即使r1被唤醒,自己因为有cpu执行权而继续打印。
所以你的问题就是出在:在线程唤醒对方线程后,没有【及时】sleep自己线程,导致了cpu执行权在一段时间内没有被释放,
即使释放了(有唤醒对方线程了),【也有可能本线程再一次夺到cpu资源】,而继续执行。(如果该线程是r2,那么它就会一段时间一直打印相同内容)
*/
synchronized void get(){
if(flag){ //当有信息时,打印信息
System.out.println(name+"的性别是"+sex);
flag=false; //打印完成后将标记置为false
notify(); //使另一线程进入唤醒状态
}//else
try{wait();}catch(Exception e){} //无信息打印时线程进入等待状态
}
}
class Input implements Runnable //输入接口类
{
private Res r;
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0) //x为0时输入
r.set("小明","男"); //调用输入方法
else //否则输入
r.set("meimei","woman");//调用输入方法
x=(x+1)%2;
}
}
}
class Output implements Runnable //输出接口类
{
private Res r;
Output(Res r){
this.r=r;
}
public void run(){
while (true)
r.get(); //调用输出方法
}
}
class InputOutputDemo
{
public static void main(String args[]){
Res r=new Res();
Runnable r1=new Input(r); //创建接口对象1
Runnable r2=new Output(r); //创建接口对象2
Thread t1=new Thread(r1); //将对象1作为参数传入创建线程1
Thread t2=new Thread(r2); //将对象2作为参数传入创建线程2
t1.start(); //开启
t2.start(); //开启
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2