[JAVA]等待通知机制的2种实现

最近笔者在空闲之余,温习了下JAVA多线程编程。经常看,却经常忘记。可能是由于用的不多的缘故吧。这里针对多线程的等待通知的机制的2种实现进行总结。加深理解和认识。

等待通知机制

首先介绍下什么是等待通知机制。这里举一个生活的例子。

大家去餐馆吃饭的时候,会取号进行”等待“。等到号了,餐馆工作人员会”通知“你前去就餐。

这就是一个简单的等待通知的例子。好了,接下来介绍下它的2种实现。

wait()和notify()实现等待通知机制

源码见Github

去餐馆就餐的客人(等待者)

package com.zju.javastudy.waitnotify.demo1;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 饿着的人,去餐馆取号,等待者
 */
public class HungryPeople implements Runnable {
    /**
     * 座位
     */
    private Object seat;

    public HungryPeople(Object seat) {
        this.seat = seat;
    }


    @Override
    public void run() {
        synchronized (seat) {
            try {
                System.out.println("HungryPeople:去餐馆吃饭,先取号...");
                seat.wait();//等待叫号
                System.out.println("HungryPeople:到号,有位置了!可以吃饭了!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

餐馆(通知者)

package com.zju.javastudy.waitnotify.demo1;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 餐馆,通知者
 */
public class Restaurant implements Runnable {
    /**
     * 座位,实质就是锁
     */
    private Object seat;

    public Restaurant(Object o) {
        this.seat = o;
    }


    @Override
    public void run() {
        try {
            //模拟等待
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (seat) {
            System.out.println("Restaurant:有空位,通知客人来就餐...");
            seat.notify();//通知到号
            System.out.println("Restaurant:完成通知");

        }

    }

}

测试

package com.zju.javastudy.waitnotidy.demo1;

import com.zju.javastudy.waitnotify.demo1.HungryPeople;
import com.zju.javastudy.waitnotify.demo1.Restaurant;
import org.junit.Test;

import static sun.jvm.hotspot.runtime.PerfMemory.start;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 餐馆取号吃饭的测试例子
 */
public class WaitNotidyTest1 {

    @Test
    public void test() throws InterruptedException {
        Object seat = new Object();//座位
        Restaurant restaurant = new Restaurant(seat);
        HungryPeople hungryPeople = new HungryPeople(seat);
        Thread hungryPeopleThread = new Thread(hungryPeople);

        hungryPeopleThread.start();
        Thread restaurantThread = new Thread(restaurant);
        restaurantThread.start();

        //子线程结束后,再结束main线程
        hungryPeopleThread.join();
        restaurantThread.join();
    }
}

结果

这里写图片描述

使用Condition实现部分通知

源码见Github

去餐馆就餐的客人(等待者)

package com.zju.javastudy.waitnotify.demo2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 饿着的人,去餐馆取号,等待者
 */
public class HungryPeople implements Runnable {
    /**
     * 所有座位
     */
    private ReentrantLock allSeat;

    /**
     * 等待的桌(大桌/小桌)
     */
    private Condition seat;


    public HungryPeople(ReentrantLock allSeat,Condition seat) {
        this.allSeat = allSeat;
        this.seat = seat;
    }


    @Override
    public void run() {
        allSeat.lock();
        try {
            seat.await();
            System.out.println(Thread.currentThread().getName()+":等到位置");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            allSeat.unlock();
        }

    }
}

餐馆(通知者)

package com.zju.javastudy.waitnotify.demo2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 餐馆,通知者
 */
public class Restaurant implements Runnable {

    /**
     * 所有座位
     */
    private ReentrantLock allSeat;

    /**
     * 小桌
     */
    private Condition smallSeat;

    /**
     * 大桌
     */
    private Condition bigSeat;

    public Restaurant(ReentrantLock allSeat,Condition smallSeat, Condition bigSeat) {
        this.allSeat = allSeat;
        this.smallSeat = smallSeat;
        this.bigSeat = bigSeat;
    }


    @Override
    public void run() {
        //这里模拟通知大桌
        try {
            allSeat.lock();
            Thread.sleep(2000);
            System.out.println("Restaurant:有大桌空位,通知客人来就餐...");
            bigSeat.signalAll();
            System.out.println("Restaurant:完成大桌通知");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            allSeat.unlock();
        }

        //这里模拟通知小桌
        try {
            Thread.sleep(3000);
            allSeat.lock();
            System.out.println("Restaurant:有小桌空位,通知客人来就餐...");
            smallSeat.signalAll();
            System.out.println("Restaurant:完成小桌通知");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            allSeat.unlock();
        }
        }
}

测试

package com.zju.javastudy.waitnotidy.demo2;

import com.zju.javastudy.waitnotify.demo2.HungryPeople;
import com.zju.javastudy.waitnotify.demo2.Restaurant;
import org.junit.Test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Arthur
 * @Date 2017/12/28
 * @Decription: 餐馆取号吃饭的测试例子
 */
public class WaitNotidyTest2 {

    @Test
    public void test() throws InterruptedException {
        ReentrantLock allSeat = new ReentrantLock();//座位
        Condition smallSeat = allSeat.newCondition();//小桌
        Condition bigSeat = allSeat.newCondition();//大桌

        //实例化 餐馆,小桌客人和大桌客人
        Restaurant restaurant = new Restaurant(allSeat,smallSeat,bigSeat);
        HungryPeople hungryPeopleWaitSmall = new HungryPeople(allSeat,smallSeat);
        HungryPeople hungryPeopleWaitBig = new HungryPeople(allSeat,bigSeat);

        //小桌客人线程
        Thread hungryPeopleWaitSmallThread = new Thread(hungryPeopleWaitSmall);
        hungryPeopleWaitSmallThread.setName("smallSeatPeople");

        //大桌客人线程
        Thread hungryPeopleWaitBigThread = new Thread(hungryPeopleWaitBig);
        hungryPeopleWaitBigThread.setName("bigSeatPeople");

        //餐馆线程
        Thread restaurantThread = new Thread(restaurant);

        //开始模拟
        hungryPeopleWaitSmallThread.start();
        hungryPeopleWaitBigThread.start();
        restaurantThread.start();

        //子线程结束再结束main线程
        hungryPeopleWaitSmallThread.join();
        hungryPeopleWaitBigThread.join();
        restaurantThread.join();
    }
}

结果

这里写图片描述

这里通过2种实现,对等待通知进制进行了一个小结。例子可能不太恰当。欢迎批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值