版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QQB67G8COM/article/details/89647969
Object对象的wait()和notify():
wait:导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法,该方法是会释放锁的。
notify:唤醒正在等待对象监视器的单个线程。 如果任何线程正在等待这个对象,其中一个被选择被唤醒。 选择是任意的,并且由实施的判断发生。 线程通过调用wait方法之一等待对象的监视器。
该方法不释放锁的。
wait和notify必须配合synchronized使用,而且wait必须在notify前用,wait后就会进入notify所在的线程,notify后唤醒wait所在的线程,但是wait所在的线程仍然没有获取锁,需要等待notify所在的线程释放锁。
代码示例:
public class WNDemo {
private volatile static List<String> list = new ArrayList<>(20);
public void add() {
list.add("ljj");
}
public int size() {
return list.size();
}
public static void main(String[] args) {
final WNDemo wDemo = new WNDemo();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized(lock) {
System.out.println("已进入t1");
for(int i = 0; i < 10; ++i) {
wDemo.add();
System.out.println("当前的线程:"+Thread.currentThread().getName()+"添加了一个元素。。");
Thread.sleep(200);
if (wDemo.size() == 5) {
lock.notify();
System.out.println("已发出通知!");
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
System.out.println("已进入t2");
if (wDemo.size() != 5) {
try {
System.out.println("t2释放锁前");
lock.wait();
System.out.println("t2释放锁后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2线程收到通知");
throw new RuntimeException();
}
}
}, "t2");
t2.start();
t1.start();
}
}
解析:
t2线程先启动并先获得锁,并执行wait()后释放锁进入阻塞状态。
t1线程获得锁,循环到5时就发出通知,但没有释放锁,直到释放锁后t2才能继续执行。
缺点:通讯延时
利用java.util.concurrent包的CountDownLatch来实现实时通讯:
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class WNDemo {
private volatile static List<String> list = new ArrayList<>(20);
public void add() {
list.add("ljj");
}
public int size() {
return list.size();
}
public static void main(String[] args) {
final WNDemo wDemo = new WNDemo();
final CountDownLatch cLatch = new CountDownLatch(1);//发出一次通知
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("已进入t1");
for(int i = 0; i < 10; ++i) {
wDemo.add();
System.out.println("当前的线程:"+Thread.currentThread().getName()+"添加了一个元素。。");
Thread.sleep(200);
if (wDemo.size() == 5) {
cLatch.countDown();
System.out.println("已发出通知!");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("已进入t2");
if (wDemo.size() != 5) {
try {
System.out.println("t2释放锁前");
cLatch.await();
System.out.println("t2释放锁后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2线程收到通知");
throw new RuntimeException();
}
}, "t2");
t2.start();
t1.start();
}
}