多线程(生产者与消费者)

需求:有一个箱子,一个男孩往里面放水果,等到箱子里满了以后,一个女孩去箱子里去水果,等箱子里水果没了,男孩再放水果进去。

1.定义一个Box类.

package org.demo;

import java.util.LinkedList;

public class Box {
 
	//定义一个集合,指定存放的是水果
	private LinkedList<Fruit> box = new LinkedList<Fruit>();
	
	//箱子提供一个put行为,让男孩往里面存放水果 
	public synchronized void put(Fruit fruit) throws Exception{
		//如果箱子是空的,那么就把水果放进箱子
		if(box.size()==5){
			System.out.println("箱子满了,通知女孩来取...");
			//wait之前必须先调用notifyAll()或者notify()方法
			this.notifyAll();
            //把自己停下,让女孩的线程来执行
			//wait方法是让当前正在执行的线程进入一个叫做等待队列的集合中
			//等待队列是由key所创建的
			//如果wait方法后面还有代码,将全部忽略
			//如果当前线程从等待队列出来后将会继续执行wait方法后的代码
			//如果当前线程进入了等待队列后,也将释放钥匙
			this.wait();
		}
		box.add(fruit);
		Thread.sleep(200);
	}
	
	//箱子提供一个take行为让女孩子提取水果
	public synchronized Fruit take() throws Exception{
		if(box.size()==0){
			System.out.println("箱子空了,通知男孩放入水果...");
			this.notifyAll();
			//将女孩的线程放入key所产生的等待队列
			this.wait();
		}
		Fruit fruit = box.removeFirst();
		Thread.sleep(200);
		return fruit;
	}
}


2.定义一个Boy类,此类继承Thread类.

package org.demo;

public class Boy extends Thread{
	
	private Box box;
	
	public Boy(Box box){
		this.box = box;
	}

	public void run(){
		//在一个死循环当中不停的调用put方法
		while(true){
			Fruit fruit = new Fruit();
			try {
				box.put(fruit);
				System.out.println("男孩放入了一个"+fruit);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

3.定义一个girl类,并且继承Thread类.

package org.demo;

public class Girl extends Thread{

	private Box box;
	
	public Girl(Box box){
		this.box = box;
	}
	
	public void run(){
		//不停的调用take方法
		while(true){
			try {
				Fruit fruit = box.take();
				System.out.println("女孩从盒子中取出一个"+fruit);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
}

4.定义一个Fruit类

package org.demo;

import java.util.Random;

public class Fruit {

	private String[] fruit = {"苹果","香蕉","葡萄","芒果","荔枝"};
	private int index;
	
	public Fruit(){
		//随机数组,返回一个下标
		index = new Random().nextInt(fruit.length);
	}
	
	//重写toString方法
	public String toString(){
		return fruit[index];
	}
}


5.演示一下

package org.demo;

public class Demo {

	public static void main(String[] args) {
		 Box box = new Box();
		 Boy boy = new Boy(box);
		 Girl girl = new Girl(box);
		 boy.start();
		 girl.start();
	}
}

多线程生产者消费者问题是一个经典的并发编程问题,主要涉及到线程间的同步和互斥。在这个问题中,有一个生产者线程和一个消费者线程,它们共享一个缓冲区。生产者线程负责往缓冲区中生产数据,而消费者线程则负责从缓冲区中消费数据。为了保证线程安全,需要使用锁或信号量等机制来实现线程间的同步和互斥。 下面是一个简单多线程生产者消费者的示例代码: ```python import threading import time # 缓冲区大小 BUFFER_SIZE = 10 # 生产者线程 class ProducerThread(threading.Thread): def __init__(self, buffer): threading.Thread.__init__(self) self.buffer = buffer def run(self): for i in range(20): # 生产数据 data = "data-%d" % i # 加锁 self.buffer.lock.acquire() # 如果缓冲区已满,等待消费者消费数据 while len(self.buffer.data) == BUFFER_SIZE: self.buffer.full.wait() # 将数据放入缓冲区 self.buffer.data.append(data) print("ProducerThread: produce %s" % data) # 释放锁 self.buffer.lock.release() # 通知消费者可以消费数据了 self.buffer.empty.notify() # 消费者线程 class ConsumerThread(threading.Thread): def __init__(self, buffer): threading.Thread.__init__(self) self.buffer = buffer def run(self): for i in range(20): # 加锁 self.buffer.lock.acquire() # 如果缓冲区为空,等待生产者生产数据 while len(self.buffer.data) == 0: self.buffer.empty.wait() # 从缓冲区中取出数据 data = self.buffer.data.pop(0) print("ConsumerThread: consume %s" % data) # 释放锁 self.buffer.lock.release() # 通知生产者可以生产数据了 self.buffer.full.notify() # 缓冲区 class Buffer: def __init__(self): self.data = [] self.lock = threading.Lock() self.full = threading.Condition(self.lock) self.empty = threading.Condition(self.lock) if __name__ == "__main__": buffer = Buffer() producer_thread = ProducerThread(buffer) consumer_thread = ConsumerThread(buffer) producer_thread.start() consumer_thread.start() producer_thread.join() consumer_thread.join() ``` 在上面的代码中,我们使用了一个列表来作为缓冲区,使用了 threading.Lock 来实现线程间的互斥,使用了 threading.Condition 来实现线程间的同步。具体来说,我们使用了 full 条件变量来表示缓冲区已满,empty 条件变量来表示缓冲区为空。当生产者线程往缓冲区中生产数据时,如果缓冲区已满,则调用 full.wait() 来等待消费者线程消费数据;当消费者线程从缓冲区中消费数据时,如果缓冲区为空,则调用 empty.wait() 来等待生产者线程生产数据。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值