JavaSE之生产消费者模型

wait()方法

1. 方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法是用来将当前线程置
入“预执行队列”中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。
2. wait()方法只能在同步方法中或同步块中调用。如果调用wait()时,没有持有适当的锁,会抛出异常
3. wait()方法执行后,当前线程释放锁,其它线程可以竞争锁。
范例:wait()的使用方法
class MyThread implements Runnable{
    private Object obj=new Object();

    public void run(){
        synchronized (obj){
            System.out.println("wait start.....");
            try {
            //如果不中断线程,线程就会一直死等
                obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait end....");
        }
    }
}
class Test {
    public static void main(String[] args) throws InterruptedException {
      MyThread myThread=new MyThread();
      Thread thread=new Thread(myThread,"A");
      thread.start();
      Thread.sleep(3000);//休眠三秒钟
      //在线程等待时中断该线程
      thread.interrupt();
    }
}
范例:wait(long timeout)的使用方法
class MyThread implements Runnable{
    private Object obj=new Object();
    public void run(){
        synchronized (obj){
            System.out.println("wait start.....");
            try {
            //如果一秒钟之内线程还没有被唤醒,一秒后线程继续执行
                obj.wait(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait end....");
        }
    }
}
class Test {
    public static void main(String[] args) throws InterruptedException {
      MyThread myThread=new MyThread();
      Thread thread=new Thread(myThread,"A");
      thread.start();
    }
}

notify()方法

notify方法就是使停止的线程继续运行。

  1. 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。如果有多个线程等待,则有线程规划器随机挑选出一个呈wait状态的线程。
  2. 在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

范例:notify()随机唤醒一个线程

class MyThread implements Runnable{
    private Object obj;
    private boolean flag;

    public MyThread(Object obj, boolean flag) {
        this.obj = obj;
        this.flag = flag;
    }

    public void waitMethod() {
        synchronized (obj) {
            System.out.println("wait start..."+Thread.currentThread().getName());

            try {
                obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("wait end...."+Thread.currentThread().getName());
        }
    }

    public void notifyMethod() {
        synchronized (obj) {
            System.out.println("notify start..." + Thread.currentThread().getName());
            obj.notify();
            System.out.println("notify end...." + Thread.currentThread().getName());
        }
    }

    @Override
    public void run() {
        if(flag){
            waitMethod();
        }else{
            notifyMethod();
        }
    }
}
class Test {
    public static void main(String[] args) throws InterruptedException {
        Object obj=new Object();
      MyThread myThread=new MyThread(obj,true);
      MyThread myThread1=new MyThread(obj,false);
      for(int i=0;i<5;i++) {
          Thread thread1 = new Thread(myThread, "等待线程"+i);
          thread1.start();
      }
      Thread thread2=new Thread(myThread1,"唤醒线程");
      Thread.sleep(1000);
      thread2.start();
    }
}

运行结果:只有随机的一个线程被唤醒,其他线程死等
在这里插入图片描述

如果想唤醒所有死等的线程,可以使用notifyAll(),用法与notify()一致。
注意:wait,notify必须使用在synchronized同步方法或者代码块内

线程阻塞

1. 线程调用 sleep()方法,主动放弃占用的处理器资源,但是不会释放对象锁。
2. 线程调用了阻塞式IO方法(read(),write()),在该方法返回前,线程被阻塞。
3. 线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。
4. 线程等待某个通知,即调用wait(),释放对象锁。
5.  程序调用了 suspend方法将该线程挂起。此方法容易导致死锁,尽量避免使用该方法。

run()方法运行结束后进入销毁阶段,整个线程执行完毕。

monitor的两个队列

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU的调度;反之,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒。

生产者与消费者模型

范例:实现多个生产者与消费者进程模型

package hhh.pre.java;

import java.util.ArrayList;
import java.util.List;

//商品类
class Goods{
    private String goodName;//商品名字
    private int count;//商品数量

    //生产了一个商品
    public synchronized void set(String goodName){
        while(count>0){
            System.out.println("商品还有很多,可以打个盹休息一下~~~");
            try {
                //等待消费者消费
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.goodName=goodName;
        this.count++;
        System.out.println(toString()+Thread.currentThread().getName());
        //唤醒等待消费的线程
        notifyAll();
    }

    public synchronized void get(){
        while(this.count==0){
            System.out.println("商品买完啦,稍等一下,我们正在拼命生产~~~");
            try {
                //等待生产者生产
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.count--;
        System.out.println(toString()+Thread.currentThread().getName());
        //唤醒生产者继续生产商品
        notifyAll();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goodName='" + goodName + '\'' +
                ", count=" + count +
                '}';
    }
}

//消费者线程
class Consumer implements Runnable{
   private Goods goods=new Goods();

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true) {
            goods.get();
        }
    }
}

//
class Producer implements Runnable{
    private Goods goods=new Goods();

    public Producer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true) {
            goods.set("MAC");
        }
    }
}
class Test {
    public static void main(String[] args) throws InterruptedException {
     Goods goods=new Goods();

     //存储多个生产、消费者线程
     List<Thread> list =new ArrayList<>();

     for(int i=0;i<10;i++){
         Thread thread=new Thread(new Consumer(goods),"消费者"+i);
         list.add(thread);
     }
     for(int i=0;i<5;i++){
         Thread thread=new Thread(new Producer(goods),"生产者"+i);
         list.add(thread);
     }
     for(Thread thread:list){
         thread.start();
     }
    }
}

运行结果:
在这里插入图片描述

发布了87 篇原创文章 · 获赞 73 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/HL_HLHL/article/details/84635369