Java中多线程的生产者和消费者的演示

Java中多线程的生产者和消费者的演示

1.多线程的操作

多线程中的生产者消费者至少操作了两个线程,如果是多生产多消费的模式则涉及到大于两个的多线程模式。
设计生产者与消费者线程,实现多生产多消费的模式。

package tread;

public class ThreadTest {
public static void main(String[] args) {
	Res res=new Res();
	Producer pro=new Producer(res);
	Consumer con=new Consumer(res);
	Thread t1=new Thread(pro);
	Thread t2=new Thread(pro);
	Thread t3=new Thread(con);
	Thread t4=new Thread(con);
	t1.start();
	t2.start();
	t3.start();
	t4.start();
}
}

//生产者
class Producer implements Runnable {
	private Res res;
	Producer(Res res) {
		this.res=res;
	}
	@Override
	public void run() {
		while(true) {
		res.set("面包");
		}
	}
	
}

//消费者
class Consumer implements Runnable{
	private Res res;
	Consumer(Res res) {
		this.res=res;
	}
	@Override
	public void run() {
		while(true) {
		res.get();
		}
	}
	
}

//资源
class Res{
	private String name;
	private int count=1;
	private boolean flag=false;
	public synchronized void set(String name) {
		while(flag)
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		this.name=name+"--"+count;
		System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
		count++;
		flag=true;
		notifyAll();
	}
	public synchronized void get() {
		while(!flag)
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		System.out.println(Thread.currentThread().getName()+"---消费者---"+this.name);
		flag=false;
		notifyAll();
	}
}

2.分析:生产者和消费者线程都有共享的资源Res,为了资源操作是同一个资源,采用创建Producer和Consumer时同时创建资源。资源中的set()与get()方法加了同步机制,避免了cpu切换线程时造成方法没执行完就执行另一个方法的问题。资源中添加了flag标记,用来判断资源是否消费完,flag初值为false,如果flag为false,则生产者生产,生产完将flag更改为true,当flag为true时,消费者开始消费,消费完成后将flag更改为false,这样就形成了一个生产和消费的循环。但是还有一个问题,我们的生产和消费线程是由cpu来自由切换的,这就会产生多次生产、多次消费的问题。所有我们要通过线程的通讯方式来约束线程的开启和冻结。首先,我们判断flag,如果flag为true时,生产者停止生产,线程冻结(wait()),如果flag为false时,生产者开始生产,生产完成后唤醒所有线程(notify All()),但是当生产者线程被唤醒并进入cpu执行时,我们设计的是一个while循环判断,这时的flag为true,所有就算开启了生产者线程,当它执行时就进入了wait()。这时唤醒并执行了消费者线程,第一步还是判断flag,如果为false,则线程进入wait(),如果为true,则进行消费行为,完成线程目标之后又唤醒所有线程(notify All()),同样还是循环判断防止消费者的多次消费问题。

运行

在这里插入图片描述

2.JDK1.5以上的Lock对象的使用

因为使用同步函数时,锁与监视器是所有对象,不能进行嵌套使用(死锁),所有每次唤醒线程需要唤醒所有线程,不合理。
解决方法:使用1.5版本以上的JDK,其中有一个Lock对象,可以代替同步函数,Lock可以同时拥有多个监视器Condition。

package thread;

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

public class ThreadLockTest {
public static void main(String[] args) {
	Res res=new Res();
	Producer pro=new Producer(res);
	Consumer con=new Consumer(res);
	Thread t1=new Thread(pro);
	Thread t2=new Thread(pro);
	Thread t3=new Thread(con);
	Thread t4=new Thread(con);
	t1.start();
	t2.start();
	t3.start();
	t4.start();
}
}

class Producer implements Runnable {
	private Res res;
	Producer(Res res) {
		this.res=res;
	}
	@Override
	public void run() {
		while(true) {
		res.set("面包");
		}
	}
	
}

class Consumer implements Runnable{
	private Res res;
	Consumer(Res res) {
		this.res=res;
	}
	@Override
	public void run() {
		while(true) {
		res.get();
		}
	}
	
}

class Res{
	private String name;
	private Lock lock=new ReentrantLock();
	//生产者监视器
	private Condition producer_con=lock.newCondition();
	//消费者监视器
	private Condition consumer_con=lock.newCondition();
	private int count=1;
	private boolean flag=false;
	public void set(String name) {
		lock.lock();
		try {
		while(flag)
			try {
				producer_con.await();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		this.name=name+"--"+count;
		System.out.println(Thread.currentThread().getName()+"---生产者---"+this.name);
		count++;
		flag=true;
		consumer_con.signal();}
		finally {lock.unlock();}
	}
	public void get() {
		lock.lock();
		try {
		while(!flag)
			try {
				consumer_con.await();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		System.out.println(Thread.currentThread().getName()+"---消费者---"+this.name);
		flag=false;
		producer_con.signalAll();}
		finally {lock.unlock();}
	}
}

运行
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值