java实现等待唤醒机制(线程交替执行)

1 等待唤醒机制

1.1举例说明

        有三个角色,食客,厨师,桌子。两个线程食客和厨师。

        厨师线程运行时,判断桌子上有没有饭,如果有则用wait()方法,让厨师线程等待,直至被其他线程唤醒,如果没有,则做饭放在桌子上,唤醒食客线程。

        食客线程运行时如果有食物则吃掉,唤醒厨师线程来做,如果没有食物则用wait()方法让食客线程等待。

1.2普通代码实现 

  • 厨师
//角色食客
public class Foodie extends Thread{
    @Override
    public void run() {
        while (true){
            synchronized (Desk.lock){
                if(Desk.count==0){
                    break;
                }else{
                    //桌子上没有食物
                    if(Desk.sign==0){
                        try {
                            //让这个线程等待。
                            Desk.lock.wait();//让当前线程与这个锁绑定
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        //桌子上有食物
                        System.out.println("食客在吃第"+Desk.count--+"碗,还能再吃"+Desk.count+"碗");
                        Desk.lock.notifyAll();//唤醒所右与这个锁绑定的线程,也就是厨师和食客,然后两者抢夺cpu,如果还是食客抢到了,则会执行上面的代码,
                        //让食客陷入次陷入等待。

                        Desk.sign=0;//修改桌子上食物的状态
                    }
                }
            }
        }
    }
}
  • 食客
//角色厨师
public class Cookie extends Thread{

    @Override
    public void run() {
        while (true){
            synchronized (Desk.lock){
                if(Desk.count==0){
                    break;
                }else{
                    //桌子上有食物
                    if(Desk.sign==1){
                        try {
                            //让这个线程等待。
                            Desk.lock.wait();//让当前线程与这个锁绑定
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        //桌子上没有食物
                        System.out.println("厨师在做第"+Desk.count+"碗");
                        Desk.lock.notifyAll();//唤醒所右与这个锁绑定的线程,也就是厨师和食客,然后两者抢夺cpu,如果还是食客抢到了,则会执行上面的代码,
                        //让食客陷入次陷入等待。
                        Desk.sign=1;//修改桌子上食物的状态
                    }
                }
            }
        }
    }
}
  •  桌子和测试类
//桌子
public class Desk {
    /**
     *  一共来回多少次
     */
    public static int count = 10;

    /**
     * 标记桌子上有没有食物
     */
    public static int sign = 0;

    /**
     * 给厨师和食客的锁
     */
    public static Lock lock=new ReentrantLock();
}

//测试类
public class TreadDemo {
    public static void main(String[] args) {
        Cook cook=new Cook();
        Foodie foodie = new Foodie();
        cook.start();
        foodie.start();
    }
}

1.3阻塞队列实现

  1.3.1阻塞队列说明

  • ArrayBlockingQueue:底层是数组,有界。

  • LinkedBlockingQueue:底层是链表,无界,但不是真正的无界,最大值为int的最大值。
  • put()方法:当队列内数据满了时,放不进去,会等着,也叫阻塞。
  • take()方法:取出第一个数据,取不到时会等着,也叫阻塞。

1.3.2阻塞队列细节说明

        在put()和take()方法内部有使用锁来保护线程安全,不需要我们在方法外再使用锁来保护数据。他们是线程安全的。  

1.3.3阻塞队列实现

//厨师
public class Cook extends Thread{
    public static ArrayBlockingQueue<String> queue;

    public Cook(ArrayBlockingQueue<String> queue){
        this.queue=queue;
    }
    @Override
    public void run() {
        while (true){
            try {
                queue.put("面条");
                System.out.println("厨师做了一个面条");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//食客
public class Foodie extends Thread{
    public static ArrayBlockingQueue<String> queue;

    public Foodie(ArrayBlockingQueue<String> queue){
        this.queue=queue;
    }

    @Override
    public void run() {
        while (true) {
            try {
                String food = queue.take();
                System.out.println("我吃了"+food);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//测试类
public class TreadDemo {
    public static void main(String[] args) {
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<String>(1);//参数为阻塞队列的大小为1.
        Cook cook=new Cook(arrayBlockingQueue);
        Foodie foodie = new Foodie(arrayBlockingQueue);
        cook.start();
        foodie.start();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_64680177/article/details/131876363
今日推荐