Java中生产者消费者问题(多个线程任务需要执行时,分别分配多个线程进行执行)详尽步骤

Ⅰ.模拟一个工厂类

属性:库存;(用来确定是否生产或者消费)
方法:生产(…){
…… ……
}
消费(…){
…… ……
}
生产方法:当库存不足时,就需要自加(模拟生产),当库存足够时,就暂停生产。
消费方法:当库存足够时,就需要自减(模拟消费),当库存不足时,就暂停消费。

public class Factory {
	// 库存
	int count;

	// 生产功能
	public synchronized void production() {
		// 当库存大于等于1时,就暂停生产
		while (count >= 1) {
			try {
				this.wait();// 线程等待
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 当库存小于1时,就开始生产
		count++;
		System.out.println(Thread.currentThread().getName() + "生产了一个商品,当前库存剩余:" + count);

		this.notifyAll();// 生产一个商品之后,就可以唤醒消费了
	}

	// 消费功能
	public synchronized void consumption() {
		// 当库存小于等于0时,就暂停消费
		while (count <= 0) {
			try {
				this.wait();// 线程等待
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 当库存大于0时,就开始消费
		count--;
		System.out.println(Thread.currentThread().getName() + "消费了一个商品,当前库存剩余:" + count);

		this.notifyAll();// 消费一个商品之后,就可以唤醒生产了
	}

}

Ⅱ.模拟两个线程任务类(生产任务,消费任务)

分别继承Runnable接口。线程任务类内部,都需要实现带参构造方法,将工厂对象作为形参,而不能在其内部直接new出工厂类对象。
原因:我们需要保证操作的是同一工厂对象,所以最好的解决办法就是在测试类中new出工厂类对象,然后在new出线程任务类对象的时候,把工厂类对象作为实参进行传递。

①生产线程任务类

//生产任务类
public class Production implements Runnable {

	Factory plant;

	public Production(Factory plant) {
		this.plant = plant;
	}

	@Override
	// 调用工厂的生产功能
	public void run() {
		//循环生产
		while (true) {
			
			plant.production();
			//生产一件商品之后,就休息1000ms
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

}

②消费线程任务类

//消费任务类
public class Consumption implements Runnable {
	
	Factory plant;

	public Consumption(Factory plant) {
		this.plant = plant;
	}

	@Override
	// 调用工厂的消费功能
	public void run() {
		//循环消费
		while (true) {
			
			plant.consumption();
			//消费一件商品之后,就休息1000ms
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

}

Ⅲ.模拟测试类

①new出工厂类对象
②new出两个线程任务类对象(生产、消费),并将工厂类对象作为实参进行传递
③new出线程对象,并将线程任务类对象进行传递
④分别启动线程

public class Test {

	public static void main(String[] args) {
		// 工厂对象
		Factory plant = new Factory();

		// 线程任务对象
			// 生产对象
		Production proTask = new Production(plant);
			// 消费对象
		Consumption conTask = new Consumption(plant);

		// 线程对象
			// 生产对象
		Thread t0 = new Thread(proTask);
		Thread t1 = new Thread(proTask);
			// 消费对象
		Thread t2 = new Thread(conTask);
		Thread t3 = new Thread(conTask);

		// 启动线程
		t0.start();
		t1.start();
		t2.start();
		t3.start();

	}

}

注:为避免多个线程同时操作一个线程任务而出错,所以我们需要实现同步
同步方法:①同步代码:工厂类内的生产和消费方法,通过synchronized( 锁对象 ){ …… }同步
②同步函数:通过synchronized修饰,直接将工厂类内的生产和消费方法同步
③Lock锁对象:创建单独的Lock锁对象,通过lock.lock();和lock.unlock();进行同步

运行后效果图

在这里插入图片描述

解释

① this.wait():线程等待,锁对象不会继续占用,立即释放锁对象
this.notifyAll():线程唤醒,唤醒时不会立即执行,仍会等到锁对象的使用
Thread.sleep(long millis):线程睡眠,锁对象将继续占用,不会释放
注: this.wait();和this.notifyAll();需配合使用,且只能用于同步中,否则会抛出异常
Thread.sleep(long millis);需传入实参(时间,单位:ms)

② Thread.currentThread().getName():获取当前进入的线程名

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值