实验内容
(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,一直执行,方便更好的观察并发执行和互斥访问