Java高并发编程-生产者消费者问题

生产者消费者模型

思路一

通过实际问题构造一个生产者和消费者问题,用馒头类,放馒头的框,生产馒头的厨师类,和吃馒头的消费者类,其中后两者实现Runnable接口,然后通过创建多个线程来生产馒头和消费馒头;

代码实现一

public class Main {
    public static void main(String[] args) {
        Bucket b = new Bucket(6);
        Producer p = new Producer(b);
        Consumer c = new Consumer(b);
        new Thread(p).start();
        new Thread(c).start();

    }
}

class Mantou {
    @Override
    public String toString() {
        return "Mantou:" + id;
    }
    int id;
    Mantou(int id) {
        this.id = id;
    }
}

class Bucket {
    int max, index;
    Mantou[] m;
    Bucket(int max) {
        this.max = max;
        index = -1;
        m = new Mantou[max];
    }

    synchronized void push(Mantou m1) {
        while (index == max-1) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.notify();
        m[++ index] = m1;
    }

    synchronized Mantou pop() {
        while (index == -1) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.notify();
        return m[index --];
    }

}

class Producer implements Runnable {
    Bucket b = null;
    Producer(Bucket b) {
        this.b = b;
    }
    @Override
    public void run() {
        for (int i=0; i<20; i++) {
            Mantou m = new Mantou(i);
            System.out.println("生产了:" + m);
            try {
                Thread.sleep((int)(Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            b.push(m);
        }
    }
}

class Consumer implements Runnable {
    Bucket b = null;
    Consumer(Bucket b) {
        this.b = b;
    }
    @Override
    public void run() {
        for (int i=0; i<20; i++) {
            Mantou m = b.pop();
            System.out.println("消费了:" + m);
        }
    }
}

思路二

通过创建同步容器来模拟生产者和消费者的问题;

代码实现二

package useful;

import java.util.ArrayList;
import java.util.List;

public class MyContainer<T> {

    private final int max = 10;
    private final List<T> list = new ArrayList<>();
//  private int count = 0;

    synchronized void put(T t) {
        while (list.size() == max) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        list.add(t);
//      count ++;
    }

    synchronized T get() {
        while (list.size() == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
//      count --;
        return list.remove(list.size()-1);
    }

    public static void main(String[] args) {
        MyContainer<String> m = new MyContainer<>();

        for (int i=0; i<10; i++) {
            new Thread(() -> {
                for (int j=0; j<5; j++) System.out.println(Thread.currentThread().getName() + " consumed " + m.get());
            }, "c" + i).start();;
        }

        for (int i=0; i<10; i++) {
            new Thread(() -> {
                for (int j=0; j<5; j++) {
                    m.put(Thread.currentThread().getName() + ":" + j);
                }
            }, "p" + i).start();;
        }
    }

}

思路三

利用Lock和Condition实现并发访问;可以精确控制到让哪一个或者哪一种线程唤醒;

代码如下

package useful;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyContainer<T> {

    private final int max = 10;
    private final List<T> list = new ArrayList<>();
    Lock lock = new ReentrantLock();
    private Condition producer = lock.newCondition();
    private Condition consumer = lock.newCondition();

    void put(T t) {
        try {
            lock.lock();
            while (list.size() == max) {
                producer.await();
            }
            list.add(t);
            consumer.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    synchronized T get() {
        T t = null;
        try {
            lock.lock();
            while (list.size() == 0) {
                consumer.await();
            }
            t = list.get(list.size()-1);
            producer.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return t;
    }

    public static void main(String[] args) {
        MyContainer<String> m = new MyContainer<>();

        for (int i=0; i<10; i++) {
            new Thread(() -> {
                for (int j=0; j<5; j++) System.out.println(Thread.currentThread().getName() + " consumed " + m.get());
            }, "c" + i).start();;
        }

        for (int i=0; i<10; i++) {
            new Thread(() -> {
                for (int j=0; j<5; j++) {
                    m.put(Thread.currentThread().getName() + ":" + j);
                }
            }, "p" + i).start();;
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值