java队列类调用notify_Java wait和notifyAll实现简单的阻塞队列

wait,会使调用的线程进入等待状态,会释放所持有的对象锁(调用的时候也必须先获取到锁,否则会抛出异常 IllegalMonitorStateException)

notifyAll、notify,会去唤醒应当前对象而等待的线程,(调用的时候也必须先获取到锁,否则会抛出异常 IllegalMonitorStateException)

顺便也记录一下join方法,调用join方法,会使当前线程进入等待,如果没有设置等待时间,就会等待另一个线程执行完成才返回(ps:调用join方法并不一定立刻执行另一个线程,只是当前线程进入等待,然后切换下一个线程)

import java.util.concurrent.atomic.AtomicInteger;

/**

* @author lhd

*/

public class BlockQueue {

/**

* 生产者锁对象

*/

private final Object addLock = new Object();

/**

* 消费者锁对象

*/

private final Object deleteLock = new Object();

/**

* 队列总大小

*/

private final Integer size = 30;

/**

* 数据存放

*/

private Object[] queue = new Object[size];

/**

* 存放的数量,使用AtomicInteger是因为普通的int递增递减操作会存在非原子性的问题,会使数量异常

*/

private AtomicInteger count = new AtomicInteger(0);

/**

* 生产

* @param o 对象

*/

public void add(Object o) {

//获取生产锁,wait方法必须获取到对象锁后才可以调用,否则抛出异常

synchronized (addLock){

//判断是否超过队列大小,超过则进入等待

while (count.get() >= size){

try {

addLock.wait();

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

//存放一个

queue[count.get()] = o;

//递增

int i = count.incrementAndGet();

//打印一下日志

String name = Thread.currentThread().getName();

System.out.println(name + "生产了一个,现有数量" + i);

}

//如果队列有数据,则调用notifyAll唤醒消费者

if (count.get() >= 1){

//notifyAll、notify都需要先获取对象锁,否则会抛出异常

synchronized (deleteLock){

deleteLock.notifyAll();

}

}

}

/**

* 消费

* @return

*/

public Object poll(){

Object o;

//先获取对象锁,和生产者类似

synchronized (deleteLock){

//队列里没有数据则等待

while (count.get() <= 0){

try {

deleteLock.wait();

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

//获取数据

o = queue[count.get()];

//递减

int i = count.decrementAndGet();

String name = Thread.currentThread().getName();

System.out.println(name + "消费了一个,现有数量" + i);

}

//如果队列没有满,则可以唤醒生产者

if (count.get() < size){

//需要先获取到锁

synchronized (addLock){

addLock.notifyAll();

}

}

return o;

}

/**

* 简单的测试

* @param args

*/

public static void main(String[] args) {

BlockQueue blockQueue = new BlockQueue();

Thread t1 = new Thread(()-> {

while (true){

blockQueue.add(new Object());

}

}

);

Thread t2 = new Thread(()-> {

while (true){

blockQueue.add(new Object());

}

}

);

Thread t3 = new Thread(()-> {

while (true){

blockQueue.add(new Object());

}

}

);

Thread t4 = new Thread(()-> {

while (true){

blockQueue.poll();

}

}

);

Thread t5 = new Thread(()-> {

while (true){

blockQueue.poll();

}

}

);

Thread t6 = new Thread(()-> {

while (true){

blockQueue.poll();

}

}

);

t1.start();

t2.start();

t3.start();

t4.start();

t5.start();

t6.start();

}

}

效果:其实这个递增递减操作和打印操作也不是原子操作

2c7b0b40a571f67b03dbc2bd3baa2f1b.png

依次打印线程1,2,3

/**

* @author lhd

*/

public class JoinTest {

public static void main(String[] args) throws InterruptedException {

Thread t1 = new Thread(() -> System.out.println(1));

Thread t2 = new Thread(()-> System.out.println(2));

Thread t3 = new Thread(()-> System.out.println(3));

t1.start();

t1.join();

t2.start();

t2.join();

t3.start();

t3.join();

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值