渚漪Day01——JavaSE笔记【死锁】&【消费者生产者问题】

死锁情况

java代码

public class Suo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		through p1 = new through(0,"小渚");
		through p2 = new through(1,"小漪");
		p1.start();
		p2.start();
	}

}
class Left{
	
}
class Right{
	
}

class through extends Thread{
	static Left left = new Left();
	static Right right = new Right();
	String Name;
	int choice;
	public through(int choice,String Name) {
		this.choice=choice;
		this.Name=Name;
	}
	
	@Override
	public void run() {
		try {
			cross();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void cross() throws InterruptedException{
		
		if(choice==0){
			synchronized (left) {//获得桥左边的锁
				System.out.println(Name+"走上独木桥左边");
				Thread.sleep(1000);
				synchronized (right) {//获得桥右边的锁
					System.out.println(Name+"走上独木桥右边");
				}
			}
		}
		else{
			synchronized (right) {//获得桥右边的锁
				System.out.println(Name+"走上独木桥右边");
				Thread.sleep(2000);
				synchronized (left) {//获得桥左边的锁
					System.out.println(Name+"走上独木桥左边");
				}
			}
		}
	}
}

此处仍处于运行状态,双方分别站在独木桥的两边,导致死锁。

生产者消费者问题

代码显示

public class pro_cus {
	public static void main(String[] args) {
		Container container = new Container();
		new Producter(container).start();
		new Customer(container).start();
	}
}


class Producter extends Thread{
	Container container;
	public Producter( Container container) {
		this.container=container;
	}
	@Override
	public void run() {
		for(int i=1;i<=20;++i)//放入20个号码的产品
		{
			container.put(new Product(i));
			System.out.println("放入了"+i+"号产品");
		}
	}
}

class Customer extends Thread{
	Container container;
	public Customer( Container container) {
		this.container=container;
	}
	@Override
	public void run() {
		for(int i=0;i<20;++i)//消费20次
		{
			System.out.println("消费了"+container.get().name+"号产品");
		}
	}
}

class Product{
	int name;
	public Product(int i){
		name=i;
	}
}

class Container{//容器存放产品
	Product[] products = new Product[10];
	int count = 0;//计数器
	
	//生产者放产品
	public synchronized void put(Product product){
		if(count==products.length){//通知消费者消费,生产者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		if(count>10)System.out.println("error");
		products[count]=product;
		count++;
		
	}
	
	//消费者取产品
	public synchronized Product get() {
		if(count==0) {//通知生产者生产,消费者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		
		count--;
		Product product = products[count];
		return product;
	}
	
}

结果显示

结果完全随机,这个结果是我认为挺能反映题目要求的结果之一。在放入1-10号产品,缓冲区并没有达到上限,故生产者可以一直生产(当然同时消费者也能一直消费,这只是情况之一)。当达到上限,生产者不能生产,而消费者仍可以进行消费。直到消费者消费完,生产者没有生产结束。

放入了1号产品
放入了2号产品
放入了3号产品
放入了4号产品
放入了5号产品
放入了6号产品
放入了7号产品
放入了8号产品
放入了9号产品
放入了10号产品
消费了9号产品
消费了10号产品
消费了11号产品
消费了8号产品
消费了7号产品
消费了6号产品
消费了5号产品
放入了11号产品
消费了4号产品
放入了12号产品
消费了12号产品
放入了13号产品
消费了13号产品
放入了14号产品
消费了14号产品
放入了15号产品
消费了15号产品
放入了16号产品
消费了16号产品
放入了17号产品
消费了17号产品
放入了18号产品
消费了18号产品
放入了19号产品
消费了19号产品
放入了20号产品
消费了20号产品
消费了3号产品
消费了2号产品
消费了1号产品

问题1

虽然基本符合题目,但仍然存在,如图,

先消费11号产品,再放入11号这样的逻辑错误

问题2

测试中,会出现放入数目count大于10的结果,但是程序并没有报错

并没有出现 java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10 这样数组越界的情况

原因

推测,程序生应该没有问题。应该是System.out.println()函数,打印时间与程序内部运行时间差较大导致。问题1是因为在执行打印“放入11号产品”前,“消费11号产品”这段话被提前打印出来。同理,问题2提前打印“放入15号产品”,但程序上已经执行完了消费14号产品导致。

改进方法

讲输出也放入get 和 put函数内部,即可解决。

当然此时IO效率会影响程序内部运行效率,每次计算都得等输出结束在进行。

public class pro_cus {
	public static void main(String[] args) {
		Container container = new Container();
		new Producter(container).start();
		new Customer(container).start();
	}
}


class Producter extends Thread{
	Container container;
	public Producter( Container container) {
		this.container=container;
	}
	@Override
	public void run() {
		for(int i=1;i<=20;++i)//放入20个号码的产品
		{
			container.put(new Product(i));
		}
	}
}

class Customer extends Thread{
	Container container;
	public Customer( Container container) {
		this.container=container;
	}
	@Override
	public void run() {
		for(int i=0;i<20;++i)//消费20次
		{
			container.get();
		}
	}
}

class Product{
	int name;
	public Product(int i){
		name=i;
	}
}

class Container{//容器存放产品
	Product[] products = new Product[10];
	int count = 0;//计数器
	
	//生产者放产品
	public synchronized void put(Product product){
		while(count>=products.length){//通知消费者消费,生产者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		if(count>10)System.out.println("error");
		products[count]=product;
		count++;
		System.out.println("放入了"+product.name+"号产品");
	}
	
	//消费者取产品
	public synchronized void get() {
		if(count==0) {//通知生产者生产,消费者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		
		count--;
		Product product = products[count];
		System.out.println("消费了"+product.name+"号产品");
	}
	
}
放入了1号产品
放入了2号产品
放入了3号产品
放入了4号产品
放入了5号产品
放入了6号产品
放入了7号产品
放入了8号产品
放入了9号产品
放入了10号产品
消费了10号产品
放入了11号产品
消费了11号产品
放入了12号产品
消费了12号产品
放入了13号产品
消费了13号产品
放入了14号产品
消费了14号产品
消费了9号产品
消费了8号产品
消费了7号产品
消费了6号产品
消费了5号产品
消费了4号产品
消费了3号产品
消费了2号产品
消费了1号产品
放入了15号产品
放入了16号产品
放入了17号产品
放入了18号产品
放入了19号产品
放入了20号产品
消费了20号产品
消费了19号产品
消费了18号产品
消费了17号产品
消费了16号产品
消费了15号产品


posted @ 2020-04-06 22:18  渚漪  阅读(159)  评论(0编辑  收藏  举报