利用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();
}
}
}