多线程之线程通信(生产者和消费者案例)

线程通信:当任务之间有关系的时候,就需要多个线程通信,互相协调一起完成工作,当然是在线程同步的基础上通信协调。

1,一般用Object的wait/notify/notifyAll,让线程等待和唤醒实现线程之间的通信,而且上述方法只能由同步监听对象(共享资源)来调用,否则会报IllegalMonitorStateException异常。

2,还可以通过ReentranLock,使用condition的await/signal来唤醒和使线程等待。

生产者和消费者案例

下面以厨师做菜和服务员上菜,给取餐台(多线程操作的资源)放菜,上菜为例,用代码实现。

1,取餐台,多线程操作的资源,资源操作的同步使用Synchronized方法和ReentrantLock两种方式实现。

/**
 * 取餐台,多线程操作的资源
 */
public class FoodTable {

    private volatile int num; // 取餐台菜的数量

    private Lock lock = new ReentrantLock(); // 可重入锁

    private Condition condition = lock.newCondition();

    /**
     * 做菜,用synchronized修饰,同一时刻只能有一个线程操作该资源对象
     * @return
     */
    public synchronized void cook() {
        try {
            while (num != 0) { // 取餐台菜品不为零,厨师不做菜
                this.wait(); // 厨师线程等待
            }
            num++; // 厨师做菜,取餐台菜品加1
            System.out.println("厨师正在做菜,做菜好忙,累死。。。");
            this.notify(); // 做好菜唤醒服务员线程上菜
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上菜,用synchronized修饰,同一时刻只能有一个线程操作该资源对象
     * @return
     */
    public synchronized void deliver() {
        try {
            while (num == 0) { // 取餐台菜品为零,服务员不用上菜
                this.wait(); // 服务员线程等待
            }
            num--; // 服务员做菜,取餐台菜品减1
            System.out.println("服务员正在上菜,简简单单上个菜,好爽。。。");
            this.notify(); // 上完菜唤醒厨师线程上菜
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 做菜,使用ReentrantLock显式保证同步,同一时刻只能有一个线程操作该资源对象
     * @return
     */
    public synchronized void cookLock() {
        try {
            lock.lock();
            while (num != 0) { // 取餐台菜品不为零,厨师不做菜
                condition.await(); // 厨师线程等待
            }
            num++; // 厨师做菜,取餐台菜品加1
            System.out.println("厨师正在做菜,做菜好忙,累死。。。");
            condition.signal(); // 做好菜唤醒服务员线程上菜
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 上菜,使用ReentrantLock显式保证同步,同一时刻只能有一个线程操作该资源对象
     * @return
     */
    public void deliverLock() {
        try {
            lock.lock();
            while (num == 0) { // 取餐台菜品为零,服务员不用上菜
                condition.await(); // 服务员线程等待
            }
            num--; // 服务员做菜,取餐台菜品减1
            System.out.println("服务员正在上菜,简简单单上个菜,好爽。。。");
            condition.signal(); // 上完菜唤醒厨师线程上菜
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

2,厨师线程

/**
 * 厨师,生产者,做菜
 */
public class Chef implements Runnable {

    private FoodTable foodTable;

    public Chef(FoodTable foodTable) { // 保证线程操作的是同一个资源,通过构造器传入同一资源对象
        this.foodTable = foodTable;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) { // 为了测试,只执行10次
            foodTable.cook(); // 做菜
        }
    }

}

3,服务员线程

/**
 * 服务员,消费者,上菜
 */
public class Waiter implements Runnable {

    private FoodTable foodTable;

    public Waiter(FoodTable foodTable) { // 保证线程操作的是同一个资源,通过构造器传入同一资源对象
        this.foodTable = foodTable;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) { // 为了测试,只执行10次
            foodTable.deliver(); // 上菜
        }
    }

}

4,测试还是用餐馆来吧QAQ

/**
 * 餐馆,厨师和服务员协调工作
 * 假设只有一个厨师和一个服务员,厨师做好菜放到取餐台,厨师等待并唤醒服务员上菜,
 * 服务员上菜,此时取餐台菜品为零,等待并唤醒厨师做菜,以此往复协调工作
 */
public class Restaurant {

    public static void main(String[] args) {
        // 实例化厨师,服务员,取餐台(资源)
        FoodTable foodTable = new FoodTable();
        Thread provider = new Thread(new Chef(foodTable)); // 创建厨师线程
        Thread consumer = new Thread(new Waiter(foodTable)); // 创建服务员线程
        provider.start(); // 厨师线程启动
        consumer.start(); // 服务员线程启动
    }

}

5,简单看下输出

厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
厨师正在做菜,做菜好忙,累死。。。
服务员正在上菜,简简单单上个菜,好爽。。。
发布了31 篇原创文章 · 获赞 0 · 访问量 1430

猜你喜欢

转载自blog.csdn.net/weixin_41645232/article/details/105607959