synchronized版本

public class Test {
	public static void main(String[] args) {

		Shared s = new Shared();
		Thread t1 = new Thread(new Product(s));
		Thread t2 = new Thread(new Consumer(s));
		t1.start();
		t2.start();
	}
}

class Product implements Runnable {

	private final Shared s;
	public Product(Shared s) {
		this.s = s;
	}
	@Override
	public void run() {
		for (char i = 'A'; i < 'Z'; i++) {
			s.setChar(i);
			System.out.println("生产者生产了一个" + i);
		}
	}
}

class Consumer implements Runnable {

	private final Shared s;
	public Consumer(Shared s) {
		this.s = s;
	}
	@Override
	public void run() {
		char c;
		do{
			c = s.getChar();
			System.out.println("消费者消费了一个" + c);
		} while(c!='Y');
	}
}

class Shared {
	
	private char ch;
	private volatile boolean writeable = true;
	public synchronized char getChar() {
		while(writeable) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		writeable = true;
		notify();
		return ch;
	}

	public synchronized void setChar(char ch) {
		while(!writeable) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		writeable = false;
		this.ch = ch;
		notify();
	}
}

ReentrantLock版本

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Test1 {

	public static void main(String[] args) {
		Shared1 s = new Shared1();
		Thread t1 = new Thread(new Product1(s));
		Thread t2 = new Thread(new Consumer1(s));
		t1.start();
		t2.start();
	}
}

class Shared1 {
	private char c;
	private volatile boolean writeable = true;
	private final ReentrantLock lock = new ReentrantLock();
	private final Condition condition = lock.newCondition();

	public void setChar(char c) {
		lock.lock();
		try {
			while (!writeable) {
				try {
					condition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			writeable = false;
			condition.signal();
			this.c = c;
		} finally {
			lock.unlock();
		}
	}
	
	public char getChar() {
		lock.lock();
		try {
			while(writeable) {
				try {
					condition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			writeable = true;
			condition.signal();
			return c;
		} finally {
			lock.unlock();
		}
	}
}
class Product1 implements Runnable {
	private Shared1 s;
	public Product1(Shared1 s) {
		this.s = s;
	}
	@Override
	public void run() {
		for (char i = 'A'; i < 'Z'; i++) {
			s.setChar(i);
			System.out.println("生产者生产了一个" + i);
		}
	}
	
}
class Consumer1 implements Runnable {
	private Shared1 s;
	public Consumer1(Shared1 s) {
		this.s = s;
	}
	@Override
	public void run() {
		char c;
		do{
			c = s.getChar();
			System.out.println("消费者消费了一个" + c);
		} while(c != 'Y');
	}
}

使用阻塞队列实现的版本

import java.util.concurrent.ArrayBlockingQueue;

public class MyBlockArray {

	public static final ArrayBlockingQueue<Character> arr = new ArrayBlockingQueue<>(26);
	public static void main(String[] args) {
		final MyBlockArray my = new MyBlockArray();
		Thread t1 = new Thread(new Product3(my));
		Thread t2 = new Thread(new Consumer3(my));
		t1.start();
		t2.start();
	}
}

class Product3 implements Runnable {
	private MyBlockArray blockArray;
	public Product3(MyBlockArray blockArray) {
		this.blockArray = blockArray;
	}
	@Override
	public void run() {
		for (char i = 'A'; i <= 'Z'; i++) {
			try {
				blockArray.arr.put(i);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("生产者生产了一个" + i);
		}
	}
	
}
class Consumer3 implements Runnable {
	private MyBlockArray blockArray;
	public Consumer3(MyBlockArray blockArray) {
		this.blockArray = blockArray;
	}
	@Override
	public void run() {
		char c = 0;
		do {
			try {
				c = blockArray.arr.take();
				System.out.println("消费者消费了一个" + c);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while(c != 'Z');
	}
}