本文将通过三个程序例子帮助读者理解其中的原理:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object();
public static void main(String[] args) throws Exception {
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.interrupt();
System.out.println(waitThread.isInterrupted());
waitThread.start();
waitThread.interrupt();
System.out.println(waitThread.isInterrupted());
TimeUnit.SECONDS.sleep(1);
}
static class Wait implements Runnable {
public void run() {
// 加锁,拥有lock的Monitor
synchronized (lock)
{
try
{
System.out.println(Thread.currentThread() + " flag is true. wait @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
}
catch (InterruptedException e)
{
System.out.println("中断");
}
System.out.println(Thread.currentThread() + " flag is false. running @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
从结果可以看出,在wait方法之前发生中断操作,将中断标志位置为true则wait方法首先将中断标志位置为false然后抛出异常,执行后续操作。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object();
public static void main(String[] args) throws Exception {
Thread waitThread = new Thread(new Wait(), "WaitThread");
// waitThread.setPriority(10);
waitThread.interrupt();
System.out.println(waitThread.isInterrupted());
waitThread.start();
waitThread.interrupt();
System.out.println(waitThread.isInterrupted());
TimeUnit.SECONDS.sleep(1);
//Thread notifyThread = new Thread(new Notify(), "NotifyThread");
//notifyThread.start();
}
static class Wait implements Runnable {
public void run() {
// 加锁,拥有lock的Monitor
synchronized (lock)
{
// 当条件不满足时,继续wait,同时释放了lock的锁
while (flag)
{
try
{
System.out.println(Thread.currentThread() + " flag is true. wait @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
}
catch (InterruptedException e)
{
System.out.println("中断");
}
}
// 条件满足时,完成工作
System.out.println(Thread.currentThread() + " flag is false. running @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
可将这个程序与上面进行比较,由于执行wait方法将中断标志位置为false,所以在下一个循环中wait方法将不会抛出异常,继续执行后续操作。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class WaitNotify {
static boolean flag = true;
static Object lock = new Object();
public static void main(String[] args) throws Exception {
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
}
static class Wait implements Runnable {
public void run() {
// 加锁,拥有lock的Monitor
synchronized (lock)
{
// 当条件不满足时,继续wait,同时释放了lock的锁
while (flag)
{
try
{
System.out.println(Thread.currentThread() + " flag is true. wait @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
}
catch (InterruptedException e)
{
System.out.println("中断");
}
}
// 条件满足时,完成工作
System.out.println(Thread.currentThread() + " flag is false. running @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
static class Notify implements Runnable
{
public void run()
{
// 加锁,拥有lock的Monitor
synchronized (lock)
{
// 获取lock的锁,然后进行通知,通知时不会释放lock的锁,
// 直到当前线程释放了lock后,WaitThread才能从wait方法中返回
System.out.println(Thread.currentThread() + " hold lock. notify @ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag = false;
SleepUtils.second(5);
}
// 再次加锁
synchronized (lock)
{
System.out.println(Thread.currentThread() + " hold lock again. sleep @ "
+ new SimpleDateFormat("HH:mm:ss").format(new Date()));
SleepUtils.second(5);
}
}
}
可将这个程序与上面的两个进行对比比较,则会发现notify和interupt方法对于wait方法不同的效果。