首先模拟单缓冲区生产者和消费者问题,wait()通常都要放入synchronized修饰的语句块中或者方法中,唤醒该线程需要调用同一对象的notify()或者notifyAll()方法
当调用某个对象notify()方法时,将从该对象等待集合中选择一个等待的线程唤醒,唤醒的线程将从等待集合中删除。
notifyAll是唤醒所有线程,只不过由于synchronized,最终只有一个线程进入
class basket{
private boolean empty;
private int good;
public basket(){
empty=true;//一开始篮子是空的
}
public synchronized void put(int value){//放入重量为value的内容
while(!empty){//当篮子不为空时
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
good=value;
System.out.println("往篮子里面放入"+good);
empty=false;
notify();
}
public synchronized void get(){//取物品
while(empty){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("从篮子里面获得"+good);
empty=true;
notify();
}
}
class producer implements Runnable{
private basket b=new basket();
public producer(basket b){
this.b=b;
}
public void run(){
for (int i=1;i<=10;i++)
b.put((int)(Math.random()*100));
}
}
class consumer implements Runnable{
private basket b=new basket();
public consumer(basket b){
this.b=b;
}
public void run(){
for (int i=1;i<=10;i++)
b.get();
}
}
public class test8 {
public static void main(String[] args) {
basket b=new basket();
producer p=new producer(b);
Thread t1=new Thread(p);
consumer c=new consumer(b);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
}
对于多缓冲区需要借助循环队列来实现存储
class basket2{
private int []a;//存储缓冲区
private int front;//队首
private int rear;//队尾
public basket2(){//初始化存储区
a=new int[10];
front=0;
rear=0;
}
public boolean isEmpty(){
return front==rear;
}
public boolean isfull(){
return (front+1)%10==rear;
}
public synchronized void put(int goods){//为满的时候循环等待
while(isfull()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
front=(front+1)%10;
a[front]=goods;
System.out.println("生产者放入"+goods);
notify();
}
public synchronized void get(){
while(isEmpty()){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
rear=(rear+1)%10;
System.out.println("消费者取出"+a[rear]);
notify();
}
}
class producer2 extends Thread{
private basket2 b=new basket2();
public producer2(basket2 b){
this.b=b;
}
public void run(){
for (int i=1;i<=100;i++)
b.put((int)(Math.random()*100));
}
}
class consumer2 extends Thread{
private basket2 b=new basket2();
public consumer2(basket2 b){
this.b=b;
}
public void run(){
for (int i=1;i<=100;i++)
b.get();
}
}
public class test9 {//一个生产者和消费者共用多个缓冲区
public static void main(String[] args) {
basket2 b=new basket2();
producer2 p=new producer2(b);
consumer2 c=new consumer2(b);
p.start();
c.start();
}
}
JDK1.5之后引入条件变量:
synchronized被Lock锁替换后,对应的监视方法wait,notify,notifyAll也要用awit,signal,signalAll操作替换。
class basket2{
private int []a;//存储缓冲区
private int front;//队首
private int rear;//队尾
private Lock lock;
private Condition full;
private Condition empty;
public basket2(){//初始化存储区
a=new int[10];
front=0;
rear=0;
lock=new ReentrantLock();
empty=lock.newCondition();
full=lock.newCondition();
}
public boolean isEmpty(){
return front==rear;
}
public boolean isfull(){
return (front+1)%10==rear;
}
public void put(int goods){//为满的时候循环等待
lock.lock();
while(isfull()){
try {
full.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
front=(front+1)%10;
a[front]=goods;
System.out.println("生产者放入"+goods);
empty.signal();
lock.unlock();
}
public void get(){
lock.lock();
while(isEmpty()){
try {
empty.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
rear=(rear+1)%10;
System.out.println("消费者取出"+a[rear]);
full.signal();
lock.unlock();
}
}
class producer2 extends Thread{
private basket2 b=new basket2();
public producer2(basket2 b){
this.b=b;
}
public void run(){
for (int i=1;i<=100;i++)
b.put((int)(Math.random()*100));
}
}
class consumer2 extends Thread{
private basket2 b=new basket2();
public consumer2(basket2 b){
this.b=b;
}
public void run(){
for (int i=1;i<=100;i++)
b.get();
}
}
public class test9 {//一个生产者和消费者共用多个缓冲区
public static void main(String[] args) {
basket2 b=new basket2();
producer2 p=new producer2(b);
consumer2 c=new consumer2(b);
p.start();
c.start();
}
}
java并发库中有一些线程安全的集合,比如可以使用ConcurrentLinkedDeque()来解决多缓冲区的生产者和消费者问题。
class basket3{
private ConcurrentLinkedDeque<Integer>list=new ConcurrentLinkedDeque<Integer>();
public void put(int n){
list.add(n);
System.out.println("向列表中装入"+n);
}
public void get(){
while(!list.isEmpty())
System.out.println("从列表中移除"+list.pollFirst());
}
}
class Producer2 implements Runnable{
basket3 b=new basket3();
public Producer2(basket3 b){
this.b=b;
}
public void run(){
for (int i=1;i<=10;i++)
b.put((int)(Math.random()*100));
}
}
class Consumer2 implements Runnable{
basket3 b=new basket3();
private Thread t;
public Consumer2(basket3 b,Thread t1){
this.b=b;
t=t1;
}
public void run(){
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i=1;i<=10;i++)
b.get();
}
}
public class test10 {
public static void main(String[] args) {
basket3 b=new basket3();
Thread t1=new Thread(new Producer2(b));
Thread t2=new Thread(new Consumer2(b,t1));
t1.start();
t2.start();
}
}