一 wait、notify、notifyAll()的基本概念

    wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。

  • 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
  • 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
  • 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

其中wait方法有三个over load方法:

wait()

wait(long)

wait(long,int)

wait方法通过参数可以指定等待的时长。如果没有指定参数,默认一直等待直到被通知。

二 代码解析

两个线程一个为Input向资源中写入数据,一个为output从资源中读取数据。当写入线程写入数据的时候,首先要对资源加锁,如果资源中没有数据,则向资源中写入数据,写入完毕后释放锁(notify),如果资源有数据,则等待,直到资源中没有数据为止才继续写入数据。

特别需要注意的的写入线程中标红的部分,else不能加上。因为两个线程都在操作同一个资源,r.isflag()为true判断完毕后,判断完毕后,r.flag可能已经为false。此时会出现与要求不符的情况。

public void
int
while (true) {
synchronized (r) {
if (r.isFlag())//如果已经有数据
{
try
r.wait();//已经阻塞线程了 阻塞之后 肯定为f.flag一定为false
} catch
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{//如果加上else,那么会出现一种情况if判断时为true,判断完毕后,r.flag已经为false。
//会出现数据不一致的情况 因此不需要加else
if
r.setName("lxb");
r.setSex("男");
}else
{
r.setName("张红");
r.setSex("女");
}
x=++x%2;
r.setFlag(true);
r.notify();//通知其他获取对象锁的线程
}
}
}
}

正确的代码如下:

package WN;

public class Input extends Thread {
	private Res r;

	public Input(Res r) {
		this.r = r;
	}

	@Override
	public void run() {
		int x = 0;
	
		while (true) {

		
			synchronized (r) {
				if (r.isFlag())//如果已经有数据
				{
					try {
						r.wait();//已经阻塞线程了 阻塞之后 肯定为f.flag一定为false
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}//如果加上else,那么会出现一种情况if判断时为true,判断完毕后,r.flag已经为false。
				//会出现数据不一致的情况 因此不需要加else
					if (x % 2 == 0) {
                        r.setName("刘泽");
                        r.setSex("男");
					}else
					{
						r.setName("张红");
						r.setSex("女");
					}
					x=++x%2;
					r.setFlag(true);
					r.notify();//通知其他获取对象锁的线程
				}
			
					
			
		}
	}
public static void main(String[] args) {
	Res r = new Res();
	Input in = new Input(r);
	
	Output out = new Output(r);
	in.start();
	out.start();
	
	
}
}
package WN;

public class Res {
	private String name;
	private String sex;
	private boolean flag=false;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public boolean isFlag() {
		return flag;
	}
	public void setFlag(boolean flag) {
		this.flag = flag;
	}

}
package WN;

public class Output extends Thread{
	private Res r;

	public Output (Res r) {
		this.r = r;
	}

	@Override
	public void run() {
		int x = 0;
		while (true) {

	
			synchronized (r) {
				if (r.isFlag())//如果已经有数据
				{
					System.out.println(r.getName()+","+r.getSex());
					r.setFlag(false);//已经取出数据
					r.notify();
				}else//没有数据
				{
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
					
			}
		}
	}

}