java多线程之间的通讯(等待和唤醒机制)
代码1:
/**
*@author StormMaybin
*@Date 2016-05-16
*@<description>线程之间的通讯(等待唤醒机制)</description>
*/
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)
{
synchronized (Input.class)
{
if (x == 0)
{
r.name = "mike";
r.sex = "nan";
}
else
{
r.name = "mary";
r.sex = "女";
}
x = (x + 1) % 2;
}
}
}
}
class Output implements Runnable
{
private Res r;
Output (Res r)
{
this.r = r;
}
public void run ()
{
while (true)
{
synchronized (Input.class)
{
System.out.println (r.name+"..."+r.sex);
}
}
}
}
class InputOutputTest
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
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();
}
}
==这个代码是一个有问题的代码,为什么呢?因为在控制输入的线程输入了性别或者姓名的时候,此时,控制输出的线程抢到cpu的执行权,打印了性别或者是姓名,但是这个姓名和性别不一定是匹配的!所以问题就出在这了!==
代码2:
class Res
{
String name;
String sex;
boolean flag = false;
}
class Input implements Runnable
{
private Res r;
Input (Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while (true)
{
synchronized (r)
{
if (r.flag)
{
try
{
r.wait();
}
catch (Exception e)
{
}
}
if (x == 0)
{
r.name = "mike";
r.sex = "nan";
}
else
{
r.name = "mary";
r.sex = "女";
}
x = (x + 1) % 2;
r.flag = true;
r.notify();
//唤醒第一个等待的线程
}
}
}
}
class Output implements Runnable
{
private Res r;
Output (Res r)
{
this.r = r;
}
public void run ()
{
while (true)
{
synchronized (r)
{
if(!r.flag)
{
try
{
r.wait();
}
catch (Exception e)
{
}
}
System.out.println (r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
class InputOutputTest
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
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类中。