java多线程 生产者与消费者

一,先不考虑线程安全的问题,对该事件分析并编写如下代码

Cake类:

package test_3;

public class Cake {
    private int sum=0;
    private static final int MAX_SIZE=20;

    public int getSum() {
        return sum;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    public void produce(String pname){
        sum++;
        System.out.println(pname+"生产了一个cake,现在还有"+sum);
    }

    public void sell(String cname){
        sum--;
        System.out.println(cname+"消费了一个cake,现在还有"+sum);
    }
}

Producer类:

package test_3;

public class Producer implements Runnable{
    private Cake cake;

    public Producer(Cake cake) {
        this.cake = cake;
    }

    @Override
    public void run() {
        for (int i=0;i<50;i++){
            cake.produce(Thread.currentThread().getName());
        }
    }
}

Consumer类:

package test_3;

public class Consumer implements Runnable{
    private Cake cake;

    public Consumer(Cake cake) {
        this.cake = cake;
    }

    @Override
    public void run() {
       for(int i=0;i<50;i++){
           cake.sell(Thread.currentThread().getName());
       }
    }
}

Main类:

package test_3;

public class Main {
    public static void main(String[] args) {
        Cake cake = new Cake();
        new Thread(new Consumer(cake),"消费者一").start();
        new Thread(new Producer(cake),"生产者一").start();
        new Thread(new Producer(cake),"生产者二").start();
        new Thread(new Consumer(cake),"消费者二").start();
    }
}

二,进行分析,需要加锁的对象为Cake,对Cake类的代码进行如下修改

package test_3;

public class Cake {
    private int sum=0;
    private static final int MAX_SIZE=20;

    public int getSum() {
        return sum;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    public synchronized void produce(String pname){
        if(sum>=MAX_SIZE){
            try {
                System.out.println("已达最大量!!!");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sum++;
        System.out.println(pname+"生产了一个cake,现在还有"+sum);
        this.notifyAll();
    }

    public synchronized void sell(String cname){
        if(sum<=0){
            try {
                System.out.println("已售完!!!");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sum--;
        System.out.println(cname+"消费了一个cake,现在还有"+sum);
        this.notifyAll();
    }
}

线程安全问题解决,如果不清楚或是思路不太清晰,可以将问题分解进行解决

三,使用lock锁实现

package test_3;

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

public class Cake_1 {
    private int sum=0;
    private static final int MAX_SIZE=20;
    private Lock lock = new ReentrantLock();

    public int getSum() {
        return sum;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    public void produce(String pname){

        if(sum>=MAX_SIZE){
            lock.lock();
            System.out.println("已达最大量!!!");
            lock.unlock();
        }
        else{
            lock.lock();
            sum++;
            System.out.println(pname+"生产了一个cake,现在有"+sum);
            lock.unlock();
        }

    }

    public synchronized void sell(String cname){

        if(sum<=0){
            lock.lock();
            System.out.println("已售完!!!");
            lock.unlock();
        }
        else{
            lock.lock();
            sum--;
            System.out.println(cname+"消费了一个cake,现在还有"+sum);
            lock.unlock();
            }
    }
}

四,使用阻塞队列BlockingQueue

package test_3;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Cake_2 {
    private BlockingQueue queue = new LinkedBlockingQueue(20);

    public void produce(String pname){
        try {
            queue.put("new cake");
            System.out.println(pname+"生产了一个cake,还有"+queue.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sell(String cname){
        try {
            queue.take();
            System.out.println(cname+"消费了一个cake,还有"+queue.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

使用阻塞对列先比前两个方法会简单一些,不需要去考虑 空 或 满 的状态,这是由于BlockingQueue 的实现LinkedBlockingQueue所决定的

猜你喜欢

转载自blog.csdn.net/qq_33371372/article/details/80247786