黑马程序员技术交流社区
标题:
关于多线程的等待唤醒机制,的理解。和步骤
[打印本页]
作者:
学习代码
时间:
2014-3-17 15:01
标题:
关于多线程的等待唤醒机制,的理解。和步骤
线程中的等待唤醒机制
/*
张三;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;男
张三;;;;;;;;;女女女女女女女
class Demo1
{
String name;
String sex;
}
class Input implements Runnable
{ private Demo1 d;
Input(Demo1 d)
{
this.d=d;
}
public void run()
{ int a=0;
while(true)
{
if(a==0)
{
d.name="张三";
d.sex="男";
}
else
{
d.name="丽丽";
d.sex="女女女女女女女";
}
a = (a+1)%2;
}
}
}
class Output implements Runnable
{
private Demo1 d;
Output(Demo1 d)
{
this.d=d;
}
public void run()
{
while(true)
{
System.out.println(d.name+";;;;;;;;;"+d.sex);
}
}
}
class Demo
{
public static void main(String[] args)
{
Demo1 d = new Demo1();
Input in =new Input(d);
Output out = new Output(d);
Thread t = new Thread(in);
Thread t1 = new Thread(out);
t.start();
t1.start();
}
}*/
//当出现 以上把“丽丽”后面加上男了 男的后面加上女了 情况说明多线程出现了安全问题
//处理方式。加上同步代码块。
/*张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
class Demo1
{
String name;
String sex;
}
class Input implements Runnable
{ private Demo1 d;
Input(Demo1 d)
{
this.d=d;
}
public void run()
{ int a=0;
while(true)
{ synchronized(d) //第一次加上同步代码块,为了解决安全问题
{
if(a==0)
{
d.name="张三";
d.sex="男";
}
else
{
d.name="丽丽";
d.sex="女女女女女女女";
}
a = (a+1)%2;
}
}
}
}
class Output implements Runnable
{
private Demo1 d;
Output(Demo1 d)
{
this.d=d;
}
public void run()
{
while(true)
{ synchronized(d) //第一次加上同步代码块,避免出现错乱 为了解决安全问题
{
System.out.println(d.name+";;;;;;;;;"+d.sex);
}
}
}
}
class Demo
{
public static void main(String[] args)
{
Demo1 d = new Demo1();
Input in =new Input(d);
Output out = new Output(d);
Thread t = new Thread(in);
Thread t1 = new Thread(out);
t.start();
t1.start();
}
}*/
/*
可是呢这样看上去结果很不好,我想让他在往里面输入值的时候吧,
输入一次,我打印一次,而不是一次性的输入很多,打印很多
这样就用到了等待唤醒机制。我在赋值的时候先判断一下,里面有没有值,
如果里面没有值的话,我就往里面输入.当里面有值的时候做一个转换的动作,
把原来的标记换成,标识里面有数据,这时候线程池中就有一条输出线程在等待,
就唤醒(notify()唤醒线程池中的第一个等待线程)输出把里面的值给输出,在他输出
完成以后,也要把标记转换成,里面没有值的情况,在唤醒在线程池中等待的输入线程
输入线程一判断没有值,就开始赋值,输入和输出交替唤醒等待(wait())。
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
这个时候就是交替打印的,输入一次打印一次。
*/
/*class Demo1
{
String name;
String sex;
boolean flag = false;
}
class Input implements Runnable
{ private Demo1 d;
Input(Demo1 d)
{
this.d=d;
}
public void run()
{ int a=0;
while(true)
{ synchronized(d) //第一次加上同步代码块,为了解决安全问题,
{ if(d.flag) //第二次加上判断标记如果有就等待,没有就赋值
try{d.wait();}catch(Exception e){}//等待
if(a==0)
{
d.name="张三";
d.sex="男";
}
else
{
d.name="丽丽";
d.sex="女女女女女女女";
}
a = (a+1)%2;
d.flag=true;//第二次加上改变判断标记。
d.notify();//第二次加上唤醒输出线程。
}
}
}
}
class Output implements Runnable
{
private Demo1 d;
Output(Demo1 d)
{
this.d=d;
}
public void run()
{
while(true)
{ synchronized(d) //第一次加上同步代码块,避免出现错乱 为了解决安全问题
{ if(!d.flag) //第二次加上判断标记如果有就输出,就等待
try{d.wait();}catch(Exception e){}
System.out.println(d.name+";;;;;;;;;"+d.sex);
d.flag=false; //第二次加上改变判断标记。
d.notify(); //第二次加上唤醒输出线程。
}
}
}
}
class Demo
{
public static void main(String[] args)
{
Demo1 d = new Demo1();
Input in =new Input(d);
Output out = new Output(d);
Thread t = new Thread(in);
Thread t1 = new Thread(out);
t.start();
t1.start();
}
}*/
//这个时候就在想如果是在多几条线程,操作输入和输出语句的话会不会有问题呢?
/*
有问题出现了
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
输出了一个 ,却打印了三个,这又是怎么回事呢?
发现这是没有判断标记造成的
为了能够每次都判断标记,把if改成了while这样每次都要判断
改完以后结果变成这样了
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
张三;;;;;;;;;男
程序挂起了不往下运行了,这又是怎么回事呢?
经解析发现原来把if该成while以后,线程全部被冻结了,所以才会出现挂起现象
分析;我们现在用的是notify()唤醒的只是一个线程,而notifyAll()唤醒的是全部线程,
现在呢我们把所有线程都唤醒看看行不行。
张三;;;;;;;;;男
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
张三;;;;;;;;;男
丽丽;;;;;;;;;女女女女女女女
丽丽;;;;;;;;;女女女女女女女
张三;;;;;;;;;男
这样时可以的。
*/
class Demo1
{
String name;
String sex;
boolean flag = false;
}
class Input implements Runnable
{ private Demo1 d;
Input(Demo1 d)
{
this.d=d;
}
public void run()
{ int a=0;
while(true)
{ synchronized(d) //第一次加上同步代码块,为了解决安全问题,
{ while(d.flag) //第二次加上判断标记如果有就等待,没有就赋值
try{d.wait();}catch(Exception e){}//等待
if(a==0)
{
d.name="张三";
d.sex="男";
}
else
{
d.name="丽丽";
d.sex="女女女女女女女";
}
a = (a+1)%2;
d.flag=true;//第二次加上改变判断标记。
d.notifyAll();//第二次加上唤醒输出线程。
}
}
}
}
class Output implements Runnable
{
private Demo1 d;
Output(Demo1 d)
{
this.d=d;
}
public void run()
{
while(true)
{ synchronized(d) //第一次加上同步代码块,避免出现错乱 为了解决安全问题
{ while(!d.flag) //第二次加上判断标记如果有就输出,就等待
try{d.wait();}catch(Exception e){}
System.out.println(d.name+";;;;;;;;;"+d.sex);
d.flag=false; //第二次加上改变判断标记。
d.notifyAll(); //第二次加上唤醒输出线程。
}
}
}
}
class Demo
{
public static void main(String[] args)
{
Demo1 d = new Demo1();
Input in =new Input(d);
Output out = new Output(d);
Thread t1 = new Thread(in);
Thread t2 = new Thread(in);
Thread t3 = new Thread(out);
Thread t4 = new Thread(out);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2