Java线程学习笔记(九)生产者消费者问题

生产者消费者模式
通过多线程和BlockingQueue实现生产者消费者模式,模拟厨师生产产品和消费者消费的过程。

用多线程来模拟生产者消费者问题。用到BlockingQueue来实现更方便和安全。

 

模拟一个厨师生成产品,消费者消费,当产品数大于10的时候厨师休息,但产品数不够时厨师接着工作。

 

 

package com.woxiaoe.study.thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 生产者 消费者 模拟
 * @author 小e
 *
 * 2010-4-29 下午09:32:43
 */

class Cook implements Runnable{
	private int productId;
	private BlockingQueue<Product> products;
	private boolean rest;
	public Cook(BlockingQueue<Product> products) {
		this.products = products;
	}
	public void product(){
		Product product = new Product(productId ++ );
		System.out.println("生产了" + product);
		products.add(product);
	}
	
	public boolean isRest() {
		return rest;
	}
	public void setRest(boolean rest){
		this.rest = rest;
	}
	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				synchronized (this) {
					while(products.size() >= 10){
						System.out.println("有剩余产品,厨师休息…………");
						rest = true;
						wait();
					}
				}
				product();// 50ms生产一个
				TimeUnit.MILLISECONDS.sleep(50);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			System.out.println("停止生产!");
		}
	}
}
class Product{
	private int productId;
	Product(int productId){
		this.productId = productId;
	}
	public int getProductId() {
		return productId;
	}
	
	@Override
	public String toString() {
		return "产品" + productId;
	}
}
class Customer implements Runnable{
	private BlockingQueue<Product> products;
	private String name;
	private Cook cook;
	public Customer(Cook cook,BlockingQueue<Product> products, String name) {
		this.cook = cook;
		this.products = products;
		this.name = name;
	}

	public void consume(){
		try {
			Product product = products.take();
			System.out.println(name + " 消费" + product);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
		}
	}

	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				consume();// 500消费一个
				synchronized (cook) {
					if(products.size() == 0 && cook.isRest()){
						cook.setRest(false);
						cook.notifyAll();
						System.out.println("库存不够,厨师开始工作……");
					}
				}
				TimeUnit.MILLISECONDS.sleep(500);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			System.out.println("用户:" + name + "停止消费!");
		}
		
	}
}
public class Restaurant {
	private Cook cook;
	
	public Restaurant(Cook cook) {
		this.cook = cook;
	}

	public static void main(String[] args) throws InterruptedException {
		
		System.out.println("饭馆开门");
		ExecutorService exec = Executors.newCachedThreadPool();
		BlockingQueue<Product> products = new LinkedBlockingQueue<Product>();
		Cook cook = new Cook(products);
		Restaurant restaurant = new Restaurant(cook);
		exec.execute(cook);
		for(int i = 0; i < 5; i++){
			exec.execute(new Customer(cook,products, "用户" +  i));
		}
		
		TimeUnit.SECONDS.sleep(2);//模拟五秒
		exec.shutdownNow();
		System.out.println("饭馆关门");
	}

}

 

 Output:

 

饭馆开门

生产了产品0

用户0 消费产品0

生产了产品1

用户1 消费产品1

生产了产品2

用户2 消费产品2

生产了产品3

用户4 消费产品3

生产了产品4

用户3 消费产品4

生产了产品5

生产了产品6

生产了产品7

生产了产品8

生产了产品9

用户0 消费产品5

生产了产品10

用户1 消费产品6

生产了产品11

用户2 消费产品7

生产了产品12

用户4 消费产品8

生产了产品13

用户3 消费产品9

生产了产品14

生产了产品15

生产了产品16

生产了产品17

生产了产品18

生产了产品19

用户0 消费产品10

生产了产品20

用户1 消费产品11

生产了产品21

用户2 消费产品12

生产了产品22

用户4 消费产品13

生产了产品23

用户3 消费产品14

生产了产品24

有剩余产品,厨师休息…………

用户0 消费产品15

用户1 消费产品16

用户2 消费产品17

用户4 消费产品18

用户3 消费产品19

用户0 消费产品20

用户:用户2停止消费!

停止生产!

用户:用户1停止消费!

用户:用户0停止消费!

用户:用户3停止消费!

用户:用户4停止消费!

饭馆关门


 

基于粒子群优化算法的p-Hub选址优化(Matlab代码实现)内容概要:本文介绍了基于粒子群优化算法(PSO)的p-Hub选址优化问题的研究与实现,重点利用Matlab进行算法编程和仿真。p-Hub选址是物流与交通网络中的关键问题,旨在通过确定最优的枢纽节点位置和非枢纽节点的分配方式,最小化网络总成本。文章详细阐述了粒子群算法的基本原理及其在解决组合优化问题中的适应性改进,结合p-Hub中转网络的特点构建数学模型,并通过Matlab代码实现算法流程,包括初始化、适应度计算、粒子更新与收敛判断等环节。同时可能涉及对算法参数设置、收敛性能及不同规模案例的仿真结果分析,以验证方法的有效性和鲁棒性。; 适合人群:具备一定Matlab编程基础和优化算法理论知识的高校研究生、科研人员及从事物流网络规划、交通系统设计等相关领域的工程技术人员。; 使用场景及目标:①解决物流、航空、通信等网络中的枢纽选址与路径优化问题;②学习并掌握粒子群算法在复杂组合优化问题中的建模与实现方法;③为相关科研项目或实际工程应用提供算法支持与代码参考。; 阅读建议:建议读者结合Matlab代码逐段理解算法实现逻辑,重点关注目标函数建模、粒子编码方式及约束处理策略,并尝试调整参数或拓展模型以加深对算法性能的理解。
好的,下面是Java多线程编程学习笔记之十二:生产者消费者模型的相关内容和代码。 ## 生产者消费者模型简介 生产者消费者模型是一种常见的多线程并发模型,它涉及到两个角色:生产者消费者生产者负责生产数据,消费者负责消费数据。生产者消费者通过一个共享的缓冲区进行通信,生产者将数据放入缓冲区,消费者从缓冲区获取数据。 在多线程编程中,生产者消费者模型的实现有多种方式,本文将介绍一种基于Java的实现方式。 ## 生产者消费者模型的实现 ### 1. 定义共享缓冲区 共享缓冲区是生产者消费者进行通信的桥梁,它需要实现以下功能: - 提供一个put方法,允许生产者将数据放入缓冲区; - 提供一个take方法,允许消费者从缓冲区获取数据; - 当缓冲区已满时,put方法应该等待; - 当缓冲区为空时,take方法应该等待。 以下是一个简单的共享缓冲区的实现: ```java public class Buffer { private int[] data; private int size; private int count; private int putIndex; private int takeIndex; public Buffer(int size) { this.data = new int[size]; this.size = size; this.count = 0; this.putIndex = 0; this.takeIndex = 0; } public synchronized void put(int value) throws InterruptedException { while (count == size) { wait(); } data[putIndex] = value; putIndex = (putIndex + 1) % size; count++; notifyAll(); } public synchronized int take() throws InterruptedException { while (count == 0) { wait(); } int value = data[takeIndex]; takeIndex = (takeIndex + 1) % size; count--; notifyAll(); return value; } } ``` 上面的Buffer类使用一个数组来表示缓冲区,size表示缓冲区的大小,count表示当前缓冲区中的元素数量,putIndex和takeIndex分别表示下一个可写和可读的位置。put和take方法都是同步方法,使用wait和notifyAll来进行线程间的等待和通知。 ### 2. 定义生产者消费者 生产者消费者都需要访问共享缓冲区,因此它们都需要接收一个Buffer对象作为参数。以下是生产者消费者的简单实现: ```java public class Producer implements Runnable { private Buffer buffer; public Producer(Buffer buffer) { this.buffer = buffer; } public void run() { try { for (int i = 0; i < 10; i++) { buffer.put(i); System.out.println("Produced: " + i); Thread.sleep((int)(Math.random() * 1000)); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Consumer implements Runnable { private Buffer buffer; public Consumer(Buffer buffer) { this.buffer = buffer; } public void run() { try { for (int i = 0; i < 10; i++) { int value = buffer.take(); System.out.println("Consumed: " + value); Thread.sleep((int)(Math.random() * 1000)); } } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 生产者在一个循环中不断地向缓冲区中放入数据,消费者也在一个循环中不断地从缓冲区中获取数据。注意,当缓冲区已满时,生产者会进入等待状态;当缓冲区为空时,消费者会进入等待状态。 ### 3. 测试 最后,我们可以使用下面的代码来进行测试: ```java public class Main { public static void main(String[] args) { Buffer buffer = new Buffer(5); Producer producer = new Producer(buffer); Consumer consumer = new Consumer(buffer); Thread producerThread = new Thread(producer); Thread consumerThread = new Thread(consumer); producerThread.start(); consumerThread.start(); } } ``` 在上面的代码中,我们创建了一个缓冲区对象和一个生产者对象和一个消费者对象,然后将它们分别传递给两个线程,并启动这两个线程。 运行上面的代码,我们可以看到生产者消费者交替地进行操作,生产者不断地向缓冲区中放入数据,消费者不断地从缓冲区中获取数据。如果缓冲区已满或者为空,生产者消费者会进入等待状态,直到缓冲区中有足够的空间或者有新的数据可用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值