java-生产者消费者模型

9 篇文章 0 订阅

利用Object类提供的wait和notify方法实现生产者消费者模型

wait()方法

wait方法用于同步代码块或者同步方法中,且锁必须是内建锁synchronized,如果使用wait时没有锁,则会抛出异常。
wait方法使得调用该方法的线程停止运行进入等待,释放对象锁,运行其他线程竞争该锁,
从运行态到阻塞态,并且将该线程置入该锁对象的等待队列中,直到接收到notify()或者被中断、终止为止。
join()方法就是对wait()方法的封装。

wait(long time)

wait(long time)方法是对wait方法的重载,可以设置等待时间,如果预计时间到了还未被唤醒,线程将继续执行。参数单位是毫秒

notify()方法

notify方法也要求必须在同步方法或者同步代码块中调用,并且必须和wait是同对象调用。
notify方法会唤醒等待队列中任意一个线程,使之从等待队列换入同步队列中,去竞争锁。
notify()语句不会在该行直接唤醒线程不会立即释放对象锁,要等待代码块执行完毕才释放对象锁。

notifyAll()

notifyAll()表示唤醒等待在该等待队列上的所有线程,换入同步队列共同去竞争锁。

在Smonitor锁对象中一共有两个队列

1.同步队列
同步队列总存放着因为竞争monitor失败导致阻塞的线程,这些线程再等待CPU调度,再次竞争锁。
2.等待队列
等待队列存放着因为调用wait方法阻塞的线程,等待队列中的线程被唤醒后会进入同步队列竞争锁。

用wait和notifyAll实现生产者消费者模型

import java.util.ArrayList;
import java.util.List;
class Goods{
    private int count;
    private int maxCount;
    public Goods(int maxCount){
        this.maxCount = maxCount;
    }
    public synchronized void set(){
        while(count>=maxCount){
            System.out.println("产品量足够");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.count++;
        System.out.println(Thread.currentThread().getName()+
                "已经生产了"+count+"个");
        notifyAll();
    }
    public synchronized void get(){
        while(count<=0){
            System.out.println("商品卖完了");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.count--;
        System.out.println(Thread.currentThread().getName()+
                "还剩"+count+"个");
        notifyAll();
    }
}
class Producer implements Runnable{
    private Goods goods;
    Producer(Goods goods){
        this.goods = goods;
    }
    @Override
    public void run() {
        while(true) {
            goods.set();
        }
    }
}
class Consumer implements Runnable{
    private Goods goods;
    Consumer(Goods goods){
        this.goods = goods;
    }
    @Override
    public void run() {
        while(true) {
            goods.get();
        }
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        Goods goods = new Goods(200);
        List<Thread>list = new ArrayList<Thread>();
        for(int i=0;i<10;i++){
        list.add(new Thread(new Producer(goods),"生产者"+i));
        list.add(new Thread(new Consumer(goods),"消费者"+i));
        }
        for(Thread i :list) {
            i.start();
        }
    }
}

利用Condition类提供的await和singnal方法实现生产者消费者模型

用Condition和Object提供的等待唤醒方法的区别

1.Conditon类提供的await和signal方法和Lock搭配是纯java实现的,具有更高的控制性和扩展性。
Object类提供的wait和notify方法和内建锁synchronized搭配这两个方法都是native本地方法和nonitor监视器搭配完成线程的等待通知机制,属于JVM的底层实现,不容易控制和扩展。
2.Condition类实现的等待通知机制支持不相应中断
Object是相应中断的
3.Condition类实现的支持多个等待队列,
Object不支持,它的等待队列只有一个
4.Conditon支持超时时间设置
Object只能设置一共等待时常,还是毫秒单位

await()方法

等待方法,同Object的wait()方法,相应中断抛异常,死等直到被中断或者唤醒

awaitUinterruptibly()

不响应中断,死等直到被唤醒

await(long time,TimeUnit unit)

同Object的wait的重载方法wait(long time)设置等待时间,当超时,中断或者被唤醒时正常返回。比Object提供的多了一个可以设置时间单位,相应中断

awaitUnit(Date deadline)

可以设置截至日期,就是不需要程序员去计算等待的时间,更不需要换算成毫秒之类的直接给出截至时间。相应中断

signal()方法

同Object的notify方法,唤醒一共再该等待队列上的线程,将该线程由等待队列转移到同步队列中去。

signalAll()

同Object提供的notifyAll方法,唤醒所有等待再该等待队列上的线程,将他们全部转移到等待队列去。注意:只是这一个等待队列中的线程被唤醒,其他等待队列的不会被唤醒

用await和signalAll方法实现生产者消费者模型

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Goods {
	private Integer count;
	private Integer maxCount;
	private Lock lock = new ReentrantLock();
	private Condition productCondition = lock.newCondition();
	private Condition consumerCondition = lock.newCondition();
	public Goods(Integer maxCount) {
		this.maxCount = maxCount;count = 0;
	}
	public void set() {
		try {
			lock.lock();
			while(count >= maxCount) {
				System.out.println("产品量饱和");
				productCondition.await();
			}
			count++;
			System.out.println(Thread.currentThread().getName() + "产品现有" + count);
			consumerCondition.signalAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	public void get() {
		try {
			lock.lock();	
			while (count <= 0) {
				System.out.println("产品卖完了");
				consumerCondition.await();
			}
		count--;
		System.out.println(Thread.currentThread().getName() + "商品还剩" + count);
		productCondition.signalAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}
class Producer implements Runnable{
	private Goods goods;
	public Producer(Goods goods){
		this.goods=goods;
	}
	@Override
	public void run() {
		while (true){
			goods.set();
		}
	}
}
class Consumer implements Runnable{
	private Goods goods;
	public Consumer(Goods goods){
		this.goods = goods;
	}
	@Override
	public void run() {
		while(true) {
			goods.get();
		}
	}
}
public class Test{
	public static void main(String[] args) throws InterruptedException {
		Goods goods = new Goods(200);
		List<Thread> list = new ArrayList<Thread>();
		for(int i=0;i<10;i++) {
			list.add(new Thread(new Producer(goods), "生产者"+i));
			list.add(new Thread(new Consumer(goods), "消费者"+i));
		}
		for(Thread i :list){
			i.start();
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值