synchronized实现的生产者消费者模式

生产者-消费者

  一个或多个生产者创建某些工作并将其置于缓冲区或队列中,一个或多个消费者会从队列中获得这些工作并完成之。这里的缓冲区或队列是临界资源。当缓冲区或队列放满的时候,生产这会被阻塞;而缓冲区或队列为空的时候,消费者会被阻塞。生产者和消费者的调度是通过二者相互交换信号完成的

这里用到了线程的并发,和同步机制,同步锁lock的使用,wait,notify的使用:
代码如下:
package lockDemo;


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class SynchronizedDemo {
public static void main(String[] args) {
//利用Lock接口和ReentrantLock类创建一个锁,作为对象唯一的标志,锁标志
Lock lock=new ReentrantLock();
//创建共享资源对象方法
Resource resource=new Resource("唛头", lock, 5);
//创建生产者线程和消费者对象线程
Productor productor=new Productor(resource);
Customer customer=new Customer(resource);
Thread thread1=new Thread(productor, "SA");
Thread thread2=new Thread(customer, "SB");
//线程启动
thread1.start();
thread2.start();

}
}
class Resource{
private String name;
private int count;//用来记录生产和消费后库存的馒头数
private boolean has=false;//保证count的安全性,数据准确性
private Lock lock;//锁对象
public Resource() {}//无参构造方法
public Resource(String name,Lock lock,int count) {//有参的构造方法,主要是传入锁对象
this.name=name;
this.lock=lock;
this.count=count;
}
//存放,生产者生产放入馒头的方法
public void push(int num) {
while(true) {//保证循环执行
synchronized (lock) {//同步代码块和同步锁对象
lock.notifyAll();//唤醒所以其它正在等待该该锁的线程
if (!has && (count+num)>=20) {//双重判定保证数据准确
try {
lock.wait();//让拥有该锁的对象睡眠,阻塞,注意必须用在同步块中
Thread.sleep(1000);//让当前线程睡眠1秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//这里将判断标志has至为原值,便于下一轮判断使用,避免因进入取走状态时候发生变化
has=false;//不可少


}else {
count+=num;
System.out.println(Thread.currentThread().getName()+"放入:"+num+" 个");
System.out.println("当前:"+count);
//这里将判断标志has至为原值,便于下一轮判断使用
has=false;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
//外取,消费者消费取走馒头方法
public void popup(int num) {
while(true) {
//这里用到has原因是为了避免两个线程都到了这里,并且此时has都是true是发生混乱
synchronized (lock) {
lock.notifyAll();
if (has && (count-num)<=0) {
try {
lock.wait();
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
has=true;

}else {
count-=num;
System.out.println(Thread.currentThread().getName()+"取走:"+num+" 个");
System.out.println("剩余"+count);
has=true;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
//其它没用枷锁的方法,显示了同步锁不会影响其它没有共享资源的方法
public void show() {
System.out.println("傻帽");
}
}


class Productor implements Runnable{
Resource resource;
public Productor() {}
public Productor(Resource resource) {this.resource=resource;}
@Override
public void run() {
//进入这里时候是随机的,先执行哪个线程的不一定,但是即某一个线程而言,一定是先执行方法show(),然后在两个线程的push和popup之间切换
resource.show();
resource.push((int)(Math.random()*5+1));
}

}
class Customer implements Runnable{
Resource resource;
public Customer() {}
public Customer(Resource resource) {this.resource=resource;}
@Override
public void run() {
//这里可以用while或for将方法包围,实现多次方法调用,也可以不用,因为方法本身带有循环题
resource.show();
//设置取走馒头的数量为随机的
int ran=(int)(Math.random()*5+1);
resource.popup(ran);
}

}
//这里要注意的是同步锁一定要放在资源共享的区域,共享的对象,类中都行,同时要保证所得唯一性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者和消费模式是一种常见的多线程编程模式,可以用于解决生产者和消费者之间的数据交换问题。在Java中,可以使用多种方式实现生产者和消费模式,比如使用wait()和notify()方法、使用BlockingQueue等。以下是一种使用wait()和notify()方法实现生产者和消费模式的示例代码: ``` public class ProducerConsumerExample { private static final int BUFFER_SIZE = 10; private static List<Integer> buffer = new ArrayList<>(BUFFER_SIZE); public static void main(String[] args) { Thread producerThread = new Thread(new Producer()); Thread consumerThread = new Thread(new Consumer()); producerThread.start(); consumerThread.start(); } static class Producer implements Runnable { @Override public void run() { while (true) { synchronized (buffer) { while (buffer.size() == BUFFER_SIZE) { try { buffer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int item = (int) (Math.random() * 100); buffer.add(item); System.out.println("Produced item: " + item); buffer.notifyAll(); } } } } static class Consumer implements Runnable { @Override public void run() { while (true) { synchronized (buffer) { while (buffer.isEmpty()) { try { buffer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int item = buffer.remove(0); System.out.println("Consumed item: " + item); buffer.notifyAll(); } } } } } ``` 在这个示例代码中,Producer和Consumer都是实现了Runnable接口的线程类。Producer线程不断地生成随机数,并将其添加到buffer中,如果buffer已满,则等待。Consumer线程不断地从buffer中取出数据,并打印出来,如果buffer为空,则等待。在每次修改buffer的时候,都需要获取buffer的锁,并在修改完成后调用notifyAll()方法来唤醒其他等待的线程。 至于"lua closure factory 完整代码"和"中文加密"的问题,我可以回答。但是请注意,这些问题的答案并不代表我是一个真正的AI,而只是一个由CSDN开发的模拟AI。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值