Java学习札记之线程模型——生产消费模型


需求:
     在生产者/消费者模型中,生产者Producer负责生产数据,而消费者Consumer负责使用数据。多个生产者线程会在同一时间运行,生产数据,并放到内存中一个共享的区域。期间,多个消费者线程读取内存共享区,消费里面的数据。
     要达到的效果就是,生产者Producer生产一件商品,消费者Consumer就消费一件。

分析:

在下面Java应用程序中,生产者线程向一个线程安全的堆栈缓冲区中写(PUSH)数据,消费者从该堆栈缓冲区中读(POP)数据,这样,这个程序中同时运行的两个线程共享同一个堆栈缓冲区资源。类Producer是生产者模型,其中的run方法中定义了生产者线程所做的操作,循环调用push()方法,不断将数据送入堆栈中,每次执行完push操作后,调用wait()方法,让线程停顿一会。类Consumer是消费者模型,循环调用pop方法,从PUPS中取出对应数据。

示意图:



class ProducerConsumerDemo 
{
	public static void main(String[] args) 
	{

		Resource r = new Resource();

		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);
		//开辟四个线程。两个消费者消费、两个生产者生产
		Thread t1 = new Thread(pro);
		Thread t3 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t4 = new Thread(con);

		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
//一个共有的资源
class Resource
{
	private String name;
	private int count = 1;
	private boolean flag = false; //标志位 当正在正在消费时为true,消费时为false
	//生产
	public synchronized void set(String name)
	{
		while(flag)
			try{this.wait();}catch(Exception e){} //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 是Object类的方法,相当于Thread.sleep(1000)的效果
		this.name = name + "---" + count++;
		System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
		flag = true;
		this.notifyAll();//唤醒其他所有的线程,就是让消费者着消费了。
	}
	//消费
	public synchronized void out()
	{
		while(!flag)
			try{wait();}catch(Exception e){}//在我消费的时候 你生产是停顿的
		System.out.println(Thread.currentThread().getName() + "..消费者........." + this.name);
		flag = false;
		this.notifyAll();//唤醒生产者线程
	}
}

class Producer implements Runnable
{
	private Resource res;
	Producer(Resource res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.set("+商品+");
		}
	}
}
class Consumer implements Runnable
{
	private Resource res;
	Consumer(Resource res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.out();
		}
	}
}

在本例中,使用了一个生产者线程和一个消费者线程,当生产者线程往堆栈中添加字符时,如果堆栈已满,通过调用this.wait方法,(这里,this就是互斥锁)把自己加入到互斥锁对象(SynchronizedStack)的锁等待队列中,如果该堆栈不满,则该生产者线程加入到互斥锁对象(SynchronizedStack)的锁申请队列中,并且很快就被JVM取出来执行。当生产者线程在执行添加生产操作的时候,消费者是不能从中取出数据的,只能在等待队列中等待,当生产者添加完数据的时候,使用this.notifyAll()(这里,this就是互斥锁)把等待队列中的所有消费者唤醒,把它加入到锁申请队列中,很快该消费者线程就会获得CPU时间。此时的生产者线程已经无法再次添加字符,因为消费者线程正在synchronized代码块中运行,JVM把生产者线程加入锁等待队列中。当消费者线程从堆栈中取完数据后,再使用this.notify()方法把生产者从等待进程中唤醒,添生产,如此循环往复,直到生产者线程和消费者线程都运行结束

当然我们在这里没有添加结束线程的条件,加一个简单的计数器就可以搞定,这里只是为了说明问题而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值