从生产者-消费者模型了解线程、同步、锁(java)

代码主要包括4个类和1个测试类:

1、Egg 类: 鸡蛋,可以由生产者放入到篮子中,供消费者消费食用。

2、Blanket 类:一个篮子,最多能装5个鸡蛋。

3、Producer 类: 生产者(可以有1个或多个,但一次只能由一个人放入1个),负责把鸡蛋放入到篮子中。

4、Customer 类 :消费者(可以有1个或多个,但一次只能由一个人吃1个), 会把篮子里的鸡蛋取走食用。

5、Tester 类 : 用于测试,可设置多个生产者和消费者。


1、Egg类,有一个ID属性,用于标识生产和消费的鸡蛋是哪一个鸡蛋,直观一点:

public class Egg {
	int id;
	public Egg (int id) {
		this.id = id;
	}
	public String toString () {
		return "鸡蛋" + id;
	}
 }



2、Blanket类,其中的放入鸡蛋(add)和吃鸡蛋(eat)方法使用了同步锁,即同一时间内只能由一个人操作篮子,放入鸡蛋或吃鸡蛋:

public class Blanket {
	int count = 0;
	Egg [] eggs = new Egg[5];

	public synchronized void eat() {
		while(count == 0){
			try{
				this.wait();//当篮子里鸡蛋数目为0时,等待生产者放入鸡蛋
			}catch(InterruptedException ex) {
				ex.printStackTrace();
			}
		}
		this.count--;
		System.out.println(Thread.currentThread().getName() + "吃了"+this.eggs[count].toString());
		this.notifyAll();
	}
	public synchronized void add(Egg e) {
		while(count == 5){
			try {
				this.wait();//当篮子里有5个鸡蛋时,先休息
			}catch(InterruptedException ex){
				ex.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "生产了:" + e.toString());
		this.eggs[count] = e;//生产鸡蛋
		count++;
		this.notifyAll();//唤醒消费者
		
	}
}



3、Producer 类,继承Runable的生产者,在条件允许(篮子鸡蛋未满)的情况不停的放入鸡蛋:
public class Producer implements Runnable{
	Blanket blanket;
	public Producer(Blanket blanket) {
		this.blanket = blanket;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			int i = blanket.count;
			Egg e = new Egg(i);
			blanket.add(e);
			try {
				Thread.sleep((int)(Math.random()*1000));
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}

}



4、Customer 类 ,继承Runable 的消费者,在篮子里有鸡蛋的时候就会去取出来吃:
public class Customer implements Runnable {
	Blanket blanket;
	public Customer(Blanket blanket) {
		this.blanket = blanket;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			blanket.eat();
			try{
				Thread.sleep((int)(Math.random()*2800));
			}catch(InterruptedException ex){
				ex.printStackTrace();
			}
		}
	}

}



5、Tester 类,用于进行测试,定义一个篮子,和1个或多个生产者,消费者,使这些生产者和消费者共用一个篮子:
public class Tester {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Blanket b = new Blanket();
		Producer p = new Producer(b);
		Producer q = new Producer(b);
		Customer c = new Customer(b);
		Customer d = new Customer(b);
		Customer e = new Customer(b);
		Customer f = new Customer(b);
		new Thread(p,"生产者A").start();
		new Thread(q,"生产者B").start();
		new Thread(c,"消费者A").start();
		new Thread(d,"消费者B").start();
		new Thread(e,"消费者C").start();
		new Thread(f,"消费者D").start();
	}

}



上面的程序运行效果如下:
生产者A生产了:鸡蛋0
消费者A吃了鸡蛋0
生产者B生产了:鸡蛋0
消费者B吃了鸡蛋0
生产者A生产了:鸡蛋0
消费者D吃了鸡蛋0
生产者A生产了:鸡蛋0
消费者C吃了鸡蛋0
生产者A生产了:鸡蛋0
生产者B生产了:鸡蛋1
消费者D吃了鸡蛋1
生产者B生产了:鸡蛋1
生产者A生产了:鸡蛋2
生产者A生产了:鸡蛋3
生产者A生产了:鸡蛋4
消费者B吃了鸡蛋4
生产者B生产了:鸡蛋5
消费者A吃了鸡蛋5
生产者A生产了:鸡蛋5
消费者B吃了鸡蛋5



它将不停的运行下去,不会出现死锁。代码的同步(synchronized)模块设置在共用的资源(篮子)中,每次只能由一名生产者或者消费者操作篮子,其他人处于等待(wait)状态,等它操作完了,它才通知其他人(notifyAll),其它人则通过竞争,然后只有一个竞争胜利的可以操作篮子,如此循环。




你可能感兴趣的:(java,thread,synchrosized)