Java wait和notifyAll实现简单的阻塞队列

网友投稿 256 2022-12-24


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.printStackTrahttp://ce();

}

}

//获取数据

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 Thrhttp://ead(()-> {

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();

}

}

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

依次打印线程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();

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Boot 整合 Shiro+Thymeleaf过程解析
下一篇:Java编程中的性能优化如何实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~