Java中wait、notify應用場景(生產者-消費者模式)

Java實現生產者消費者的方式有:wait && notify、BlockingQueue、Lock && Condition等

wait、notify注意事項:
(1)可以使用wait()和notify()方法在Java中實現線程間通信。不只是一個或兩個線程,而是多個線程可以使用這些方法相互通信。
(2)在synchronized方法或synchronized塊中調用wait(),notify()和notifyAll()方法
(3)從while(條件)循環調用wait和notify方法,而不是從if()塊調用,因爲要重複檢查條件,而不僅僅是一次。
(4)使用notifyAll方法而不是notify,喚醒所有消費端。

相關代碼 

MiddlewareChannel類-存儲生產者消息的通道 

package com.java.test;

import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * 存儲 生產者消息的通道
 * @author jiajie
 *
 */
public class MiddlewareChannel {
	public int init_capacity=0;//初始存儲  
	public int max_capacity=20;//最大存儲 最大容量值
	
	
	
	/**
	 * 		  消息端產生消息
	 * 		  
	 * @param message
	 */
	public synchronized void send() {
		//判斷通道是否已滿
		if(init_capacity > max_capacity) {   //已滿
			try {
				System.out.println("庫存已滿,生產者等待發送信息...");
				//生產者  等待發送消息
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else {
			
			//通知消費者 消費消息
			System.out.println(Thread.currentThread().getName()+":生產消息" +"庫存容量:"+(++init_capacity));
			//喚醒所有消費者
			notifyAll();
		}
		
	}
	
	/**
	 * 消息端 消費消息
	 */
	public synchronized void accept() {
		//判斷通道是否有消息
		if (init_capacity>0) {  //通道有消息
			 //彈出消息
			 System.out.println(Thread.currentThread().getName()+":消費消息:"+" 庫存容量:"+(--init_capacity));
			//消費完喚醒生產者 生產消息
		    notifyAll();
		}else {           //通道無消息
			try {
				System.out.println("庫存不足,等待生產者生產消息...");
				//等待消費
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

Producer生產者

package com.java.test;

/**
 * 生產者
 * @author jiajie
 *
 */
public class Producer implements Runnable{
	private MiddlewareChannel middlewareChannel;
	private String threadName;
	private String message;
	

	/**
	 * 構造通道類
	 * @param middlewareChannel
	 */
	public Producer(MiddlewareChannel middlewareChannel) {
		this.middlewareChannel = middlewareChannel;
	}

	/**
	 * 生產消息
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub
//		while (true) {
//			System.out.println(Thread.currentThread().getName());
//			middlewareChannel.send(message);
//		}
		
		for (int i = 0; i < 20; i++) {
//			System.out.println(Thread.currentThread().getName());
			middlewareChannel.send();
		}
	}
	
	
}

Conumer消費者 

package com.java.test;

import javax.sound.midi.MidiChannel;

/**
 * 消費者
 * @author jiajie
 *
 */
public class Conumer implements Runnable{
	private MiddlewareChannel middlewareChannel;

	public Conumer(MiddlewareChannel middlewareChannel) {
		
		this.middlewareChannel = middlewareChannel;
	
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
//			System.out.println(Thread.currentThread().getName());
			middlewareChannel.accept();
		}
	
	}
	
}

 

測試

package com.java.test;

public class ClientTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//創建消息通道
		MiddlewareChannel middlewareChannel = new MiddlewareChannel();
		
		
		//創建消息消費者
		Conumer conumer1 = new Conumer(middlewareChannel);
		new Thread(conumer1,"消費者1").start();
		
//		//創建消息消費者
//		Conumer conumer2 = new Conumer(middlewareChannel);
//		new Thread(conumer2, "消費者2").start();
		
		//創建消息生產者1
		Producer producer1 = new Producer(middlewareChannel);
		new Thread(producer1,"生產者1").start();
		
//		//創建消息生產者2
//		Producer producer2 = new Producer(middlewareChannel, "我愛加班");
//		new Thread(producer2,"生產者2").start();
		
		
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章