该Demo模仿插入和取出栈顶的数据
- 变量的声明
private int top = -1; // 栈顶
private int[] mData = new int[1024];// 存储数据的数组
private boolean isAlive = false; // 此时栈顶是否有数据
- 取出栈顶数据
当执行查询操作时查看标志位(栈顶是否有数据)
假设结果为true那么取出数据并重置标志位,否则wait。
public int pop() {
synchronized (this) {
while (!isAlive) {
try {
System.out.println("释放对象锁-->pop");
wait();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
System.out.println("被唤起-->pop");
isAlive = false;// 设置标志位为false
int i = mData[top--];
notifyAll();// 唤醒此时正在等待压入数据的线程
return i;
}
}
- 向栈顶插入数据
当执行查询操作时查看标志位(栈顶是否有数据)
假设结果为false那么插入数据并重置标志位,否则wait。
public void push(int i) {
synchronized (this) {
System.out.println("拿到对象锁-->push");
while (isAlive) {
try {
System.out.println("释放对象锁-->push");
wait();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
System.out.println("压入数据-->push");
mData[++top] = i;
isAlive = true;// 设置标志位为true
notifyAll();// 唤醒此时正在等待取出栈顶数据的现成
}
}
测试类长这样
public class Test {
public static void main(String[] args) {
final Stack stack = new Stack();
Thread thread = new Thread() {
@Override
public void run() {
System.out.println(stack.pop() + "");
}
};
thread.start();
Thread thread2 = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stack.push(1);
}
};
thread2.start();
}
}
运行结果
拿到对象锁-->pop
释放对象锁-->pop
拿到对象锁-->push
压入数据-->push
被唤起-->pop
1
流程如下
- 线程A拿到线程锁–>查看标志位–>结果为false–>进入wait释放掉线程锁–>线程B拿到线程锁–>查看标志位–>结果为flase–>反转为true–>插入数据–>重置标志位–>唤醒线程A–>线程A重新检查标志位状态–>假设此时标志位true–>取出数据重置标志位–>唤醒正在等待的线程