记录
this.notify();
功能:不是唤醒正在执行this.notify();的当前线程
而是唤醒一个现在正在等待(wait) this对象 的其它线程
如果有多个线程正在等待(wait) this对象 ,通常是唤醒最先等待(wait) this对象 的线程
但具体唤醒哪一个,是由系统调度器控制的,程序员无法控制
aa.wait();将执行aa.wait();的当前线程转入阻塞状态,让出CPU的控制权
释放对aa的锁定
需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
aa.notify();假设执行aa.notify();的当前线程为T1,如果当前时刻有其他线程因为执行了aa.wait()而陷入阻塞状态,则唤醒其中一个
所谓唤醒是令该线程从因wait而陷入阻塞的状态转入就绪状态
若在执行aa.notify();前没有线程处于wait状态,那么程序也不会出错,相当于唤醒了0个线程
aa.notifyAll()唤醒其它所有的因执行了aa.wait()而陷入阻塞状态的线程
在多线程中要测试某个条件的变化,使用if 还是while?
选用while在多线程情况下,在wait过程中cnt可能会被其它线程修改,导致恢复后条件仍然成立
notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。所以在进行条件判断时候,可以先把 wait 语句忽略不计来进行考虑;显然,要确保程序一定要执行,并且要保证程序直到满足一定的条件再执行,要使用while进行等待,直到满足条件才继续往下执行。
以下是简易的生产消费问题:
public class produceConsume {
public static void main(String[] args) {
SynStack ss = new SynStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
Thread t1 = new Thread(p); // 生产线程
Thread t2 = new Thread(c); // 消费线程
t1.start();
t2.start();
}
}
class SynStack {
private char[] data = new char[6];
private int cnt = 0; // 表示数组有效元素个数
public synchronized void push(char ch)
{
while(cnt == data.length) // 为什么不用if 【在多线程情况下,在wait过程中cnt可能会被其它线程修改,导致恢复后条件仍然成立】
{
// 暂停
try {
System.out.println("exc push wait");
this.wait();
} catch (Exception e) {
e.printStackTrace();
System.out.println("push wait error");
}
System.out.println("push resume");
}
this.notify();
data[cnt] = ch;
cnt++;
System.out.printf("生产线程正在生产第%d个产品:%c\n", cnt, ch);
}
public synchronized char pop()
{
char ch;
while(cnt == 0)
{
// 暂停
try {
// System.out.println("exc pop wait");
this.wait();
} catch (Exception e) {
System.out.println("pop error");
}
System.out.println("pop resume");
}
// System.out.println("awake");
this.notify();
ch = data[cnt - 1];
System.out.printf("消费线程正在消费第%d个产品:%c\n", cnt, ch);
--cnt;
return ch;
}
}
class Producer implements Runnable {
private SynStack ss = null;
public Producer(SynStack ss)
{
this.ss = ss;
}
public void run()
{
char ch;
for (int i = 0; i < 20; i++) {
// try {
// Thread.sleep(1000);
// } catch (Exception e) {
// e.printStackTrace();
// }
ch = (char)('a' + i);
ss.push(ch);
}
}
}
class Consumer implements Runnable {
private SynStack ss = null;
public Consumer(SynStack ss)
{
this.ss = ss;
}
public void run()
{
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
ss.pop();
}
}
}
祭夜の咖啡馆 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:[笔记]Java多线程学习之wait,notify,notifyAll