码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-10-01 21:09:57      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:dsa   class   ring   san   not   sys   jdk1.5   tar   dex   

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之多线程基础(2)消费者和生产者关系

标签:dsa   class   ring   san   not   sys   jdk1.5   tar   dex   

原文地址:http://www.cnblogs.com/gg128/p/7617771.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!