一:概念性
1.wait()和notify()方法必须放在synchronized块中执行,否则没有意义意味着调用wait()和notify方法必须获得锁的控制权。
2.wait()和sleep()的区别为线程调用wait()方法会将锁释放掉,运行别的线程占有锁,自己进入等待队列。
而sleep()只是暂时休眠,不会将手里的锁释放掉
3.notif方法会唤醒等待队列中的第一个线程,不会通知优先级高的。被唤醒的进程与其他线程平等竞争cpu资源
二:实例分析
package thread;
class Res{
public boolean flag = true;
public String name;
}
class inputThread extends Thread{
public Res res;
public inputThread(Res res) {
this.res=res;
}
@Override
public void run() {
System.out.println("我是写");
int count=0;
while (true) {
synchronized (res) {
if (res.flag) {
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count==0) {
System.out.println("写入lucy");
res.name="lucy";
}else {
System.out.println("写入jack");
res.name="Jack";
}
count =(count+1)%2;
res.flag=true;
res.notify();
}
}
}
}
class readThread extends Thread{
public Res res;
public readThread(Res res) {
this.res=res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("读"+res.name);
res.flag=false;
res.notify();
}
}
}
}
public class ConmunicatThreadTest {
//开启两个线程 下面的线程 主线程 还有这俩用户线程 cpu随机的
public static void main(String[] args) {
Res res = new Res();
inputThread inputThread = new inputThread(res);
readThread readThread = new readThread(res);
inputThread.start();
readThread.start();
}
}
1.初始值flag=true,写进程抢到锁,开始进入synchronized 代码块,因为此时flag为true,执行wait()方法,释放手中的锁,这时候写进程抢到锁因为此时flag=true,所以不执行wait()直接开始读。。。而此时因为就没有执行写入操作就释放了锁,所以自然也就取不到值所以读为null
2.执行完读取操作后继续顺序执行 res.flag=false;res.notify();因为这是个while循环所以会继续执行while中的代码块,而此时flag状态为flase就会进入写入操作模块,将数据写入后,执行 res.flag=true; res.notify();再次进入循环语句时,执行wait(),释放手中的锁,唤醒读线程,
3.读线程拿到cpu资源,因为此时flag=true.,所以讲内容输出来,继续执行以上操作不断写入。。读取 写入。。。读取
三.wait释放锁,使用notify只是把它唤醒,可以和其他线程公平抢占资源。但是他不是一定会抢到。举个栗子
package thread;
public class RunA implements Runnable{
private Object lock;
public RunA(Object lock) {
this.lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (lock){
try {
System.out.println("A begin");
// lock.wait(); // 永远等待着,不会执行下去
lock.wait(2000);// 等待了2秒之后,继续执行下去
System.out.println("A end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package thread;
public class RunB implements Runnable {
private Object lock;
public RunB(Object lock) {
this.lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (lock) {
System.out.println("b come");
while (true) {
}
}
}
}
package thread;
public class TestRunAandB {
public static void main(String args[]) throws InterruptedException{
Object lock = new Object();
Thread threadA = new Thread(new RunA(lock));
threadA.start();
/*threadA.wait();
Thread.sleep(1000);*/
Thread.sleep(1000);
Thread threadB = new Thread(new RunB(lock));
threadB.start();
}
}
A线程抢到资源后,先输出A begin 等待2S后,A线程被唤醒,可是没有抢到锁所以没有输出A end;