多线程之生产者与消费者

博客围绕生产者消费者问题展开,该问题是典型的线程交互问题。使用栈存放数据,对栈进行线程安全改造及边界操作处理。提供生产者、消费者线程类和测试类,实现两个生产者和三个消费者线程同时运行。还给出了MyStack类、生产者类、消费者类及主函数的编写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程之生产者与消费者

问题描述

生产者消费者问题是一个非常典型性的线程交互的问题。

  1. 使用栈来存放数据
    1.1 把栈改造为支持线程安全
    1.2 把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。 当栈里的数据是200的时候,访问push的线程就会等待
  2. 提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈
  3. 提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台
  4. 提供一个测试类,使两个生产者和三个消费者线程同时运行,结果类似如下 :

在这里插入图片描述

程序编写

  1. MyStack类

描述:
MyStack类用于描述数据的压栈和出栈,这里用泛型来表示

package DuoXianCheng;

import java.util.LinkedList;

public class MyStack<T> {

	private LinkedList<T> list;
	private int count;
	
	public MyStack() {
		list = new LinkedList<>();
		count = 0;
	}
	
	public synchronized int getSize() {
		return count;
	}
	
	//压栈
	public synchronized void push(T ele) {
		
		while(count >= 200) {
			try {
				this.wait();
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		list.addLast(ele);
		count++;
		
		this.notifyAll();
	}
	
	//出栈
	public synchronized T pull() {
		
		while(count <= 0) {
			try {
				this.wait();
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		
		T res = list.pollLast();
		count--;
		
		this.notifyAll();
		return res;
	}
	
	//查看最后的数据,不取出
	public synchronized T peek() {
		return list.peekLast();
	}
}

  1. 生产者类

描述:
生产者类用于对英文字母的压栈操作,多线程用实现Runnable接口来实现

package DuoXianCheng;

import java.util.Random;

public class Producer implements Runnable{

	private MyStack<Character> stack;
	
	public Producer(MyStack<Character> stack) {
		this.stack = stack;
	}
	
	public void run() {
		while(true) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			char c = generateChar();
			stack.push(c);
			System.out.println("Procucer pushed: " + c + " " + stack.getSize());
		}
	}

	private char generateChar() {

		return (char) (new Random().nextInt(26) + 'A');//随机生成英文
	}
	
}

  1. 消费者类

描述:
生产者类用于出栈操作,多线程也是用实现Runnable接口来实现的

package DuoXianCheng;

public class Consumer implements Runnable{

	private MyStack<Character> stack;
	
	public Consumer(MyStack<Character> stack) { 
		this.stack = stack;
	}
	
	public void run() {
		while(true) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Consumer pulled: " + stack.pull() + " " + stack.getSize());
			
		}
	}
	
}


  1. 主函数

描述:
两个生产者和三个消费者同时进行

package DuoXianCheng;

/*
	1. 使用栈来存放数据
		1.1 把栈改造为支持线程安全
		1.2 把栈的边界操作进行处理,当栈里的数据是0的时候,访问pull的线程就会等待。 
			当栈里的数据时200的时候,访问push的线程就会等待
	2. 提供一个生产者(Producer)线程类,生产随机大写字符压入到堆栈
	3. 提供一个消费者(Consumer)线程类,从堆栈中弹出字符并打印到控制台
	4. 提供一个测试类,使两个生产者和三个消费者线程同时运行,结果类似如下 :
 */
public class ShengChanZheXiaoFeiZhe {

	
	public static void main(String[] args) {
		
		MyStack<Character> stack = new MyStack<>();
		
		for (int i = 0; i < 3; i++) {
			new Thread(new Producer(stack)).start();//参数为一个带有runnable接口改写了run方法的对象
			
		}
			
		for (int i = 0; i < 2; i++) {
			new Thread(new Consumer(stack)).start();
		}
		
	}
	
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值