java 生产者与消费者的几种实现方式

java 生产者与消费者的几种实现方式

1 synchronized的方式


public class MyClass {

    public static void main(String[] args){
        final DataAssemble dataAssemble = new DataAssemble();
        for(int i = 0; i < 20; i ++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dataAssemble.productor();
                }
            },"生产者" + i);
            thread.start();
        }

        for(int i = 0; i < 30; i ++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dataAssemble.consumer();
                }
            },"消费者" + i);
            thread.start();
        }
    }
}

public class DataAssemble {

    private static final int size = 10;
    private LinkedList<Data> datas = new LinkedList<>();
    
    public synchronized void consumer(){
        try {
            while (datas.size() == 0){
                System.out.println(Thread.currentThread().getName() + "仓库里没有了");
                wait();
            }
            datas.poll();
            System.out.println(Thread.currentThread().getName() +"消费者消费了data" + "and size = " + datas.size());
            notify();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public synchronized void productor(){
        try {
            while (datas.size() == size){
                System.out.println(Thread.currentThread().getName()+"仓库里数据满了");
                wait();
            }
            datas.add(new Data());
            System.out.println(Thread.currentThread().getName() + "生产者生产了data" + "and size = " + datas.size());
            notify();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static class Data{
    }
}

运行结果:

生产者0生产者生产了dataand size = 1
生产者12生产者生产了dataand size = 2
生产者11生产者生产了dataand size = 3
生产者10生产者生产了dataand size = 4
生产者9生产者生产了dataand size = 5
生产者8生产者生产了dataand size = 6
生产者7生产者生产了dataand size = 7
生产者6生产者生产了dataand size = 8
生产者5生产者生产了dataand size = 9
生产者4生产者生产了dataand size = 10
生产者3仓库里数据满了
生产者2仓库里数据满了
生产者1仓库里数据满了
生产者19仓库里数据满了
生产者18仓库里数据满了
生产者17仓库里数据满了
生产者16仓库里数据满了
生产者15仓库里数据满了
生产者14仓库里数据满了
消费者2消费者消费了dataand size = 9
生产者13生产者生产了dataand size = 10
生产者2仓库里数据满了
消费者4消费者消费了dataand size = 9
消费者3消费者消费了dataand size = 8
生产者3生产者生产了dataand size = 9
消费者1消费者消费了dataand size = 8
消费者7消费者消费了dataand size = 7
消费者0消费者消费了dataand size = 6
生产者15生产者生产了dataand size = 7
消费者10消费者消费了dataand size = 6
生产者14生产者生产了dataand size = 7
生产者2生产者生产了dataand size = 8
消费者9消费者消费了dataand size = 7
消费者8消费者消费了dataand size = 6
生产者16生产者生产了dataand size = 7
生产者17生产者生产了dataand size = 8
消费者6消费者消费了dataand size = 7
生产者18生产者生产了dataand size = 8
生产者19生产者生产了dataand size = 9
消费者16消费者消费了dataand size = 8
消费者5消费者消费了dataand size = 7
生产者1生产者生产了dataand size = 8
消费者19消费者消费了dataand size = 7
消费者20消费者消费了dataand size = 6
消费者18消费者消费了dataand size = 5
消费者17消费者消费了dataand size = 4
消费者22消费者消费了dataand size = 3
消费者15消费者消费了dataand size = 2
消费者14消费者消费了dataand size = 1
消费者13消费者消费了dataand size = 0
消费者25仓库里没有了
消费者12仓库里没有了
消费者27仓库里没有了
消费者11仓库里没有了
消费者26仓库里没有了
消费者29仓库里没有了
消费者24仓库里没有了
消费者23仓库里没有了
消费者21仓库里没有了
消费者28仓库里没有了

注意这里面必须使用while循环判断,if循环判断会导致notify之后阻塞在wait的线程继续往下执行,引发BUG

 while (datas.size() == 0){
                System.out.println(Thread.currentThread().getName() + "仓库里没有了");
                wait();
            }

2 ReentrantLock实现

public class DataAssembleReLock {

    private static final int size = 10;
    private LinkedList<DataAssemble.Data> datas = new LinkedList<>();
    private ReentrantLock lock = new ReentrantLock();
    private Condition empty = lock.newCondition();
    private Condition full = lock.newCondition();

    public void consumer(){
        try {
            lock.lock();
            while (datas.size() == 0){
                System.out.println(Thread.currentThread().getName() + "仓库里没有了");
                empty.await();
            }
            datas.poll();
            System.out.println(Thread.currentThread().getName() +"消费者消费了data" + "and size = " + datas.size());
            full.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void productor(){
        try {
            lock.lock();
            while (datas.size() == size){
                System.out.println(Thread.currentThread().getName()+"仓库里数据满了");
                full.await();
            }
            datas.add(new DataAssemble.Data());
            System.out.println(Thread.currentThread().getName() + "生产者生产了data" + "and size = " + datas.size());
            empty.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static class Data{
    }
}

3 阻塞队列实现

public class DataAssembleBlockQueue {

    private static final int size = 10;
    private BlockingQueue<Data> queue = new ArrayBlockingQueue<Data>(size);

    public void consumer(){
        try {
            queue.take();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public  void productor(){
        try {
            queue.put(new DataAssembleBlockQueue.Data());
            
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static class Data{
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值