假设线程1需要等待线程2执行之后才执行,实现方法有多种,最佳的实现方法是线程2执行后,通知线程1可以执行了。这就引出了Object类中的wait()、notify()、notifyAll()方法。
1、wait()
当2个线程1执行时,调用了wait(),那么2个线程1会放弃已抢到的锁,进入阻塞状态。
2、notify、notifyAll
当线程2执行notify时,会唤醒2个线程中的某一个,重新回到就绪状态。若是执行notifyAll后,会唤醒所有线程1进入就绪状态。
测试代码如下:
测试一、2个线程1及一个线程2使用notify
private String name;
private static final byte[] flag=new byte[0];
public Test03(String name) {
this.name=name;
}
@Override
public void run() {
synchronized (flag) {
try {
System.out.println(name+" wait 之前");
flag.wait();
System.out.println(name+" wait 之后");
Thread.sleep(1000L);
System.out.println(name+" sleep 之后");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService es=Executors.newCachedThreadPool();
es.execute(new Test03("线程一"));
es.execute(new Test03("线程二"));
es.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000L);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (flag) {
System.out.println("唤醒");
flag.notify();
}
}
});
es.shutdown();
}
测试一结果:
线程一 wait 之前
线程二 wait 之前
唤醒
线程一 wait 之后
线程一 sleep 之后
测试二、2个线程1及一个线程2使用notifyAll
private String name;
private static final byte[] flag=new byte[0];
public Test03(String name) {
this.name=name;
}
@Override
public void run() {
synchronized (flag) {
try {
System.out.println(name+" wait 之前");
flag.wait();
System.out.println(name+" wait 之后");
Thread.sleep(1000L);
System.out.println(name+" sleep 之后");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService es=Executors.newCachedThreadPool();
es.execute(new Test03("线程一"));
es.execute(new Test03("线程二"));
es.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000L);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (flag) {
System.out.println("唤醒");
flag.notifyAll();
}
}
});
es.shutdown();
}
测试二结果:
线程一 wait 之前
线程二 wait 之前
唤醒
线程二 wait 之后
线程二 sleep 之后
线程一 wait 之后
线程一 sleep 之后
可以看到,测试一使用notify后,只有一个线程1被唤醒,而使用notifyAll后两个线程1都被唤醒。