wait和notify
1 wait()方法是Object类的方法,它的作用是使当前执行wait方法的线程等待,在wait所在的代码行处暂停执行,并释放锁,直到接到通知或中断。2 notify()方法是用来通知那些可能等待该锁的其他线程,如果有多个线程等待,则按照执行wait方法的顺序发出一次性通知(一次只能通知一个),使得等待排在第一顺序的线程获得锁,执行notify方法后,当前线程不会立即释放锁,要等到线程执行完,即
原文链接:wait和notify – 编程屋
1 wait()方法是Object类的方法,它的作用是使当前执行wait方法的线程等待,在wait所在的代码行处暂停执行,并释放锁,直到接到通知或中断。
2 notify()方法是用来通知那些可能等待该锁的其他线程,如果有多个线程等待,则按照执行wait方法的顺序发出一次性通知(一次只能通知一个),使得等待排在第一顺序的线程获得锁,执行notify方法后,当前线程不会立即释放锁,要等到线程执行完,即退出synchronized同步区域后。
总结:
1)wait方法使线程暂停运行,而notify方法通知暂停的线程继续运行。
2)wait方法会释放锁,notify方法不会释放锁
3)wait释放锁之后回来继续执行时,必须先拿到锁,否则不会执行。
接下来可以用小程序来验证一下:
小程序:实现一个容器,提供两个方法,add、size
写两个线程,线程1添加10个元素到容器中、线程2实现监控元素的个数,当个数到5时,线程2给出提示并结束。
volatile List lists = new ArrayList();
public void add(Object o){lists.add(o);}
public int size(){return lists.size();}
public static void main(String[] args) {
T03_NotifyHoldingLock c = new T03_NotifyHoldingLock();
final Object lock = new Object();
new Thread(()->{
synchronized (lock){
System.out.println("t2启动");
if (c.size() != 5 ) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2结束");
}
},"t2").start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("t1启动");
synchronized (lock){
for (int i = 0; i < 10; i++) {
c.add(new Object());
System.out.println("add"+i);
if (c.size() ==5 ) {
lock.notify();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t1").start();
}
解析:在main线程里面,先启动t2线程,然后进行阻塞,之后执行t1线程,进行数值的累加,加到长度为5时进行唤醒。按照道理来说,此时t2线程应该继续执行了,但是事实是不是这样呢?
运行结果:
可以看到结果:即是进行看唤醒t2线程也是在t1线程执行完之后才继续运行的。那这是为什么呢?
因为虽然此时对t1线程进行了唤醒,但是锁并没有释放,所以还是需要等待t1线程执行完成释放锁,才会去执行早已唤醒的t2线程。
那么怎么解决这个问题呢?需要在t1线程满足条件之后释放锁。进行一个wait(lock.wait();),还需要在t2线程结束之后唤醒notify线程t1。
改动1:
改动2:
完整代码:
volatile List lists = new ArrayList();
public void add(Object o){lists.add(o);}
public int size(){return lists.size();}
public static void main(String[] args) {
T03_NotifyHoldingLock c = new T03_NotifyHoldingLock();
final Object lock = new Object();
new Thread(()->{
synchronized (lock){
System.out.println("t2启动");
if (c.size() != 5 ) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2结束");
//通知t1继续执行
lock.notify();
}
},"t2").start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("t1启动");
synchronized (lock){
for (int i = 0; i < 10; i++) {
c.add(new Object());
System.out.println("add"+i);
if (c.size() ==5 ) {
lock.notify();
//释放锁 让t2线程得以执行
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t1").start();
}
运行结果:
以上只是部分内容,为了维护方便,本文已迁移到新地址:wait和notify – 编程屋
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)