java之多线程基础消费者和生产者关系

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java之多线程基础消费者和生产者关系相关的知识,希望对你有一定的参考价值。

1.多线程重复出现某结果   如下:已经卖完了和仓库已经满了会出现多次

public class ProductAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Product product = new Product(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(product).start();
		new Thread(consumer).start();
	}
}

class Clerk {
	private int goodsNumber = 0;

	public synchronized void get() {
		if(goodsNumber<=10){
		System.out.println("商品A库存数量为:"+ ++goodsNumber);
		}else{
			System.out.println("仓库已经满了");
		}
	}
	public synchronized void sale(){
		if(goodsNumber>0){
			System.out.println("商品A库存数量为:"+ --goodsNumber);
		}else{
			System.out.println("已经卖完了");
		}
	}
}
class Product implements Runnable{
	private Clerk  clerk;
	public Product(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.get();
		}
	}
}
class Consumer implements Runnable{
	private Clerk  clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.sale();
		}
	}
}

 2. 多线程同步锁造成死锁,如下:商人找买家先要钱,买家找商人先要货造成死锁,原因在于:一个不释放锁,另一个得不到锁

public class GoodsAndMoney {
	public static void main(String[] args) {
		Trader trader = new Trader(buyer.money);
		buyer buyer = new buyer(Trader.goods);
		new Thread(trader).start();
		new Thread(buyer).start();
	}
}

class Trader implements Runnable {
	public static String goods = "goods";
	public static String money;

	public Trader(String money) {
		Trader.money = money;
	}

	@Override
	public void run() {
		while (true) {
			synchronized (goods) {
				synchronized (money) {
				}
			}
			System.out.println("先交钱~后交货~");
		}
	}
}

class buyer implements Runnable {
	public static String money = "money";
	public static String goods;

	public buyer(String goods) {
		buyer.goods = goods;
	}
	@Override
	public void run() {
		while (true) {
			synchronized (money) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (goods) {
				}
			}
			System.out.println("先交货~后交钱~");
		}

	}
}

  3.虚假唤醒,如下:当最后一次出现卖完了的时候,出售线程处于wait状态,所以线程不会结束

public class ProductAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Product product = new Product(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(product).start();
		new Thread(consumer).start();
	}
}

class Clerk {
	private int goodsNumber = 0;

	public synchronized void get() {
		if(goodsNumber<1){
		System.out.println("商品A库存数量为:"+ ++goodsNumber);
		this.notifyAll();
		}else{
			System.out.println("仓库已经满了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	public synchronized void sale(){
		if(goodsNumber>0){
			System.out.println("商品A库存数量为:"+ --goodsNumber);
			this.notifyAll();
		}else{
			System.out.println("已经卖完了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Product implements Runnable{
	private Clerk  clerk;
	public Product(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.get();
		}
	}
}
class Consumer implements Runnable{
	private Clerk  clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.sale();
		}
	}
}

  4.虚假唤醒,线程进入wait后会释放线程的锁,后面的线程有可能到wait位置,被唤醒后,两个线程运行后导致结果超出范围

package volatile1;

public class ProductAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Product product = new Product(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(product).start();
		new Thread(consumer).start();
		new Thread(product).start();
		new Thread(consumer).start();
	}
}

class Clerk {
	private int goodsNumber = 0;

	public synchronized void get() {
		if (goodsNumber >= 5) {
			System.out.println("仓库已经满了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + ++goodsNumber);
		this.notifyAll();
	}

	public synchronized void sale() {
		if (goodsNumber <= 0) {
			System.out.println("已经卖完了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + --goodsNumber);
		this.notifyAll();
	}
}

class Product implements Runnable {
	private Clerk clerk;
	public Product(Clerk clerk) {
		this.clerk = clerk;
	}

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.get();
		}
	}
}

class Consumer implements Runnable {
	private Clerk clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.sale();
		}
	}
}

 5.在4的代码上加上循环可以解决虚假唤醒,因为被唤醒后会经过while需要满足条件才能跳出,而且第一次到while里时值会变化,所以不会连着出现已经满了

package volatile1;

public class ProductAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Product product = new Product(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(product).start();
		new Thread(consumer).start();
		new Thread(product).start();
		new Thread(consumer).start();
	}
}

class Clerk {
	private int goodsNumber = 0;

	public synchronized void get() {
		while (goodsNumber >= 5) {
			System.out.println("仓库已经满了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + ++goodsNumber);
		this.notifyAll();
	}

	public synchronized void sale() {
		while (goodsNumber <= 0) {
			System.out.println("已经卖完了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + --goodsNumber);
		this.notifyAll();
	}
}

class Product implements Runnable {
	private Clerk clerk;
	public Product(Clerk clerk) {
		this.clerk = clerk;
	}

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.get();
		}
	}
}

class Consumer implements Runnable {
	private Clerk clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.sale();
		}
	}
}

  5.jdk1.5以后的lock方法解决以上问题

package volatile1;

public class ProductAndConsumer2 {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Product product = new Product(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(product).start();
		new Thread(consumer).start();
		new Thread(product).start();
		new Thread(consumer).start();
	}
}

class Clerk {
	private int goodsNumber = 0;

	public synchronized void get() {
		while (goodsNumber >= 5) {
			System.out.println("仓库已经满了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + ++goodsNumber);
		this.notifyAll();
	}

	public synchronized void sale() {
		while (goodsNumber <= 0) {
			System.out.println("已经卖完了");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("商品A库存数量为:" + --goodsNumber);
		this.notifyAll();
	}
}

class Product implements Runnable {
	private Clerk clerk;
	public Product(Clerk clerk) {
		this.clerk = clerk;
	}

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.get();
		}
	}
}

class Consumer implements Runnable {
	private Clerk clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			clerk.sale();
		}
	}
}

  

以上是关于java之多线程基础消费者和生产者关系的主要内容,如果未能解决你的问题,请参考以下文章

Java基础之多线程Stack类

Java之多线程

python并发编程之多线程守护系列互斥锁生产者消费者模型

Java核心技术点之多线程2

Java 多线程基础生产者与消费者

JAVA SE基础篇60.线程协作