生产者消费者问题(java多线程)

实验内容

(1)设置存放产品的缓冲区的个数为6个。
(2)信号量机制实现生产者和消费者对缓冲区的互斥访问。
(3)生产者生产产品时,要输出当前缓冲区冲产品的个数和存放产品的位置。
(4)消费者消费产品时,要输出当前缓冲区冲产品的个数和消费产品的位置。
(5)用多线程的并发实现生产者进程和消费者进程的同步。

实验原理

为了使生产者进程和消费之进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可以从一个缓冲区中取走产品去消费。
假定在生产者和消费者之间的公用缓冲池具有n个缓冲区,这是可以利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量notfull和notempty分别表示缓冲池中满缓冲区和空缓冲区的数量。同时假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费之便可以从缓冲池取走一个消息。
Semaphore是一个计数信号量,它的本质是一个"共享锁"。信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。计数为0的Semaphore是可以release的,然后就可以acquire(即一开始使线程阻塞从而完成其他执行。)。

代码

class Producer implements Runnable {
    Clerk clerk = new Clerk();
    public Producer(Clerk clerk){
        this.clerk = clerk;
    }
    @Override
    public void run() {
        try {
            clerk.getNotFull().acquire();
            clerk.getMutex().acquire();
            clerk.getList().add(new Object());
            System.out.println("【生产者" + Thread.currentThread().getName() +
                    "】生产一个产品,产品存放位置为:" + clerk.getList().size() +
                    ",现库存:" + clerk.getList().size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                clerk.getMutex().release();
                clerk.getNotEmpty().release();
            }
    }
}

class Consumer implements Runnable {
    Clerk clerk = new Clerk();
    public Consumer(Clerk clerk){
        this.clerk = clerk;
    }
    @Override
    public void run() {
        try {
            clerk.getNotEmpty().acquire();
            clerk.getMutex().acquire();
            clerk.getList().remove();
            System.out.println("【消费者" + Thread.currentThread().getName() +
                    "】消费一个产品,消费产品位置为:" + (clerk.getList().size() + 1) +
                    ",现库存:" + clerk.getList().size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                clerk.getMutex().release();
                clerk.getNotFull().release();
            }

    }
}

import java.util.LinkedList;
import java.util.concurrent.Semaphore;
public class Clerk {
    private LinkedList<Object> list = new LinkedList<Object>();
    // 仓库的最大容量
    Semaphore notFull = new Semaphore(6);
    public void setNotFull(Semaphore notFull) {
        this.notFull = notFull;
}

    public void setNotEmpty(Semaphore notEmpty) {
        this.notEmpty = notEmpty;
}

    public void setMutex(Semaphore mutex) {
        this.mutex = mutex;
}

    public LinkedList<Object> getList() {
        return list;
}

    public void setList(LinkedList<Object> list) {
        this.list = list;
}

    public Semaphore getNotFull() {
        return notFull;
}

    public Semaphore getNotEmpty() {
        return notEmpty;
}

    public Semaphore getMutex() {
        return mutex;
}

    // 将线程挂起,等待其他来触发
    Semaphore notEmpty = new Semaphore(0);
    // 互斥锁
    Semaphore mutex = new Semaphore(1);
}

public class Demo_ProducerComsumer {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        int t = 12;
        while(t-- != 0){
            new Thread(new Producer(clerk)).start();
            new Thread(new Consumer(clerk)).start();
        }

    }
}

运行结果

多线程并发执行12次之后的结果,在此也可以让它while里面的参数变量为true,一直执行,方便更好的观察并发执行和互斥访问
在这里插入图片描述

posted @ 2020-10-22 17:07  AC_沫离  阅读(270)  评论(0)    收藏  举报