三种方法简单实现生产者与消费者
方法一:使用wait()和notifyAll()
使用synchronized同步锁机制,线程先获得对象的锁,先上锁后执行线程内容,执行完成后释放锁。
/**
* 使用wait()和notifyAll()简单实现生产者与消费者
*/
public class Test1 {
private static int count = 0;//记录当前剩余“产品”量
private static final int FULL = 10;//最大容量
private static Object obj = new Object();
public static void main(String[] args) {
Test1 test1 = new Test1();
new Thread(test1 .new Producer()).start();
new Thread(test1 .new Consumer()).start();
new Thread(test1 .new Producer()).start();
new Thread(test1 .new Consumer()).start();
}
class Producer implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (obj){
while(count == FULL){
try {
obj.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
count++;
System.out.println("生产后:"+count);
obj.notifyAll();
}
}
}
}
class Consumer implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
try{
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (obj){
while (count == 0){
try{
obj.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
count--;
System.out.println("消费后:"+count);
obj.notifyAll();
}
}
}
}
}
执行结果之一:
方法二:使用ReentrantLock
ReentrantLock是显示锁,他可以和Condition联用,它的作用就是代替Object的那些监视器方法,Condition 中的await()、signal()和signalAll()方法分别对应着Object的wait()、notify()和notifyAll()方法。一个lock可以关联多个Condition,使用起来比较灵活
/**
* 使用ReentrantLock简单实现生产者与消费者
*/
public class Test2 {
private static int count = 0;
private static final int FULL = 10;
//创建锁对象
private Lock lock = new ReentrantLock();
//创建两个条件变量,一个为缓冲区非满,一个为缓冲区非空
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public static void main(String[] args) {
Test2 test2 = new Test2();
new Thread(test2 .new Producer()).start();
new Thread(test2 .new Consumer()).start();
new Thread(test2 .new Producer()).start();
new Thread(test2 .new Consumer()).start();
}
class Producer implements Runnable{
@Override
public void run() {
for(int i=0; i<10; i++){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
//获取锁
lock.lock();
try{
while(count == FULL){
try{
notFull.await();
}catch (InterruptedException e){
e.printStackTrace();
}
}
count++;
System.out.println("生产后:"+count);
//唤醒消费者
notEmpty.signal();//唤醒一个等待进程
}finally {
lock.unlock();
}
}
}
}
class Consumer implements Runnable{
@Override
public void run() {
for(int i=0; i<10; i++){
try{
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
lock.lock();
try {
while(count == 0){
try{
notEmpty.await();//阻塞,等待生产者生产
}catch (Exception e){
e.printStackTrace();
}
}
count--;
System.out.println("消费后:"+count);
notFull.signal();
}finally {
lock.unlock();
}
}
}
}
}
执行结果之一:
方法三:使用阻塞队列
创建一个阻塞队列,在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
/**
* 使用阻塞队列简单实现生产者与消费者
*/
public class Test3 {
private static int count = 0;
//创建阻塞队列
final BlockingDeque bq =new LinkedBlockingDeque<>(10);
public static void main(String[] args) {
Test3 test3 = new Test3();
new Thread(test3 .new Test2.Producer()).start();
new Thread(test3 .new Test2.Consumer()).start();
new Thread(test3 .new Test2.Producer()).start();
new Thread(test3 .new Test2.Consumer()).start();
}
class Producer implements Runnable{
@Override
public void run() {
for(int i=0; i<10; i++){
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
try{
bq.put(1);
count++;
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
@Override
public void run() {
for (int i=0; i<10; i++){
try{
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
try {
bq.take();
count--;
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
执行结果之一: