Java多线程编程之多生产多消费者示例

示例:分别创建并启动五个线性用于生产鸡蛋,消费鸡蛋;且鸡蛋最多可以有10个,消费鸡蛋只能是生产好了的鸡蛋,完成一边生产鸡蛋,一边消费鸡蛋的模型。

创建一个鸡蛋资源类EggRes,该类中封装有鸡蛋个数count,行为有生产鸡蛋,消费鸡蛋两个方法,

用同步锁来解决同步问题,等待唤醒机制完成线程间通讯,正常完成多生产多消费功能实现;

鸡蛋资源类EggRes代码如下:

class EggRes {
	//最多能同时存在鸡蛋10个
	int count;
	boolean flag = true;
	public void product() {
		//鸡蛋小于10个时,生产鸡蛋线程为唤醒状态;鸡蛋为10个以上时,等待状态;
		while (true) {
			//执行while循环目的是使该线程可以生产很多鸡蛋,而不是生产一个鸡蛋就执行结束了
			if (count >= 10) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} 
			
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println("线程" + Thread.currentThread().getName() + ",生产了鸡蛋:" + ++count );
			//每次生产一次鸡蛋,该线程就释放出锁,给予其他生产线程,消费线程竞争锁的机会
			try {
				wait(3000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			//此时,消费线程肯定为唤醒状态,那么唤醒所有线程
			notifyAll();
		}
		
	}
	
	public void consumer() {
		//鸡蛋大于0个时,消费鸡蛋线程为唤醒状态; 鸡蛋为0时,等待状态
		
		while (true) {
			if (count <= 0) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//模拟消费鸡蛋需要耗时2s,这里线程没有释放出锁
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println("线程" + Thread.currentThread().getName() + ",消费了鸡蛋:" + count--);
			
			//每次消费一次鸡蛋,该线程就释放出锁,给予其他生产线程,消费线程竞争锁的机会
			try {
				wait(3000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			//此时,生产线性必须为唤醒状态,唤醒全部线程
			notifyAll();
			
		}
	}
		
}

生产线程类和消费线程类需要共享鸡蛋资源类EggRes的数据,于是通过构造函数传参获取共享数据;代码如下:

//生产线程
class MyProductThread extends Thread {

	private EggRes er;
	public MyProductThread(EggRes er) {
		this.er = er;
	}

	@Override
	public void run() {
		synchronized (er){
			er.product();
		}
	}
}


//消费线程
class MyConsumerThread extends Thread {
	private EggRes er;
	
	public MyConsumerThread(EggRes er) {
		this.er = er;
	}

	@Override
	public void run() {
		synchronized (er) {
			er.consumer();
		}
	}
}

主函数调用如下:

public class MulProduct2Consumer {

	public static void main(String[] args) {
		//生产线程,消费线程的共享资源类EggRes
		EggRes er = new EggRes();
		
		MyProductThread[] mpts = new MyProductThread[5];
		for (int i = 0; i < mpts.length; i++) {
			mpts[i] = new MyProductThread(er);
			mpts[i].start();
		}
		
		MyConsumerThread[] mcts = new MyConsumerThread[5];
		for (int i = 0; i < mcts.length; i++) {
			mcts[i] = new MyConsumerThread(er);
			mcts[i].start();
		}
		
	}

}

完整代码如下:

public class MulProduct2Consumer {

	public static void main(String[] args) {
		//生产线程,消费线程的共享资源类EggRes
		EggRes er = new EggRes();
		
		MyProductThread[] mpts = new MyProductThread[5];
		for (int i = 0; i < mpts.length; i++) {
			mpts[i] = new MyProductThread(er);
			mpts[i].start();
		}
		
		MyConsumerThread[] mcts = new MyConsumerThread[5];
		for (int i = 0; i < mcts.length; i++) {
			mcts[i] = new MyConsumerThread(er);
			mcts[i].start();
		}
		
	}

}

//鸡蛋类
class EggRes {
	//最多能同时存在鸡蛋10个
	int count;
	boolean flag = true;
	public void product() {
		//鸡蛋小于10个时,生产鸡蛋线程为唤醒状态;鸡蛋为10个以上时,等待状态;
		while (true) {
			//执行while循环目的是使该线程可以生产很多鸡蛋,而不是生产一个鸡蛋就执行结束了
			if (count >= 10) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} 
			
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println("线程" + Thread.currentThread().getName() + ",生产了鸡蛋:" + ++count );
			//每次生产一次鸡蛋,该线程就释放出锁,给予其他生产线程,消费线程竞争锁的机会
			try {
				wait(3000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			//此时,消费线程肯定为唤醒状态,那么唤醒所有线程
			notifyAll();
		}
		
	}
	
	public void consumer() {
		//鸡蛋大于0个时,消费鸡蛋线程为唤醒状态; 鸡蛋为0时,等待状态
		
		while (true) {
			if (count <= 0) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//模拟消费鸡蛋需要耗时2s,这里线程没有释放出锁
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println("线程" + Thread.currentThread().getName() + ",消费了鸡蛋:" + count--);
			
			//每次消费一次鸡蛋,该线程就释放出锁,给予其他生产线程,消费线程竞争锁的机会
			try {
				wait(3000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			//此时,生产线性必须为唤醒状态,唤醒全部线程
			notifyAll();
			
		}
	}
		
}

//生产线程
class MyProductThread extends Thread {

	private EggRes er;
	public MyProductThread(EggRes er) {
		this.er = er;
	}

	@Override
	public void run() {
		synchronized (er){
			er.product();
		}
	}
}


//消费线程
class MyConsumerThread extends Thread {
	private EggRes er;
	
	public MyConsumerThread(EggRes er) {
		this.er = er;
	}

	@Override
	public void run() {
		synchronized (er) {
			er.consumer();
		}
	}
}
截取部分打印结果:

线程Thread-3,生产了鸡蛋:1
线程Thread-5,消费了鸡蛋:   1
线程Thread-4,生产了鸡蛋:1
线程Thread-2,生产了鸡蛋:2
线程Thread-1,生产了鸡蛋:3
线程Thread-4,生产了鸡蛋:4
线程Thread-5,消费了鸡蛋:   4
线程Thread-3,生产了鸡蛋:4
线程Thread-9,消费了鸡蛋:   4
线程Thread-0,生产了鸡蛋:4
线程Thread-9,消费了鸡蛋:   4
线程Thread-3,生产了鸡蛋:4
线程Thread-5,消费了鸡蛋:   4
线程Thread-4,生产了鸡蛋:4
线程Thread-1,生产了鸡蛋:5
线程Thread-2,生产了鸡蛋:6
线程Thread-8,消费了鸡蛋:   6
线程Thread-6,消费了鸡蛋:   5
线程Thread-7,消费了鸡蛋:   4
线程Thread-8,消费了鸡蛋:   3

你可能感兴趣的:(java)