java多线程通信之等待唤醒机制

0概述

多线程间通信,其实就是多个线程操操作同一个资源,但是操作方式不同。典型实例有生产者和消费者,本文也通过实例来分析线程等待唤醒机制。

1相关API介绍

public final void notify()
唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会任意选择唤醒其中一个线程
public final void wait()
当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。
“为了实现监视器的排他性监视能力,JVM为每一个对象和类都关联一个锁;锁住了一个对象,就是获得对象相关联的监视器”。
wait(),notify(),notifyAll(),这些方法都使用在同步代码块中,因为要对持有监视器的线程进行操作,所以要使用在同步中,因为只有同步才有锁。值得说明的是:等待和唤醒必须是同一个锁(必须为同一个对象)由于锁可以是任意对象,所以可以被任意对象调用的方法定义在object类中

2 实例分析

仓库类

//等待和唤醒都是this锁
public class Storage<T> {
    // 仓库最大存储量
    private final int MAX_SIZE = 1000;
    private int storageSize = 100;
    private Object[] data;
    private int top = 0;


    public Storage(int size) {
        size = size <= 0 ? storageSize : size;
        size = size > this.MAX_SIZE ? this.MAX_SIZE : size;
        this.storageSize = size;
        data = new Object[this.storageSize];
    }

    public int getStorageSize() {
        return storageSize;
    }

    public synchronized T pop() {
        while (top == 0) {
            try {
                //等待
                wait();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        top--;
        T t = (T) data[top];
        //唤醒所有线程
        notifyAll();
        return t;
    }

    public synchronized void push(T t) {
        while (top == storageSize) {
            try {
                wait();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        data[top++] = t;
        notifyAll();
    }

}

生产者

public class Producer implements Runnable {
    private Storage<String> storage;
    private volatile boolean breakLoop = false;

    public Producer(Storage<String> storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        int index = 1;
        while (true) {
            if (breakLoop) {
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            storage.push("data:" + index);
            System.out.println("Producer data:" + index);
            index++;
        }
    }

    public void destroy() {
        this.breakLoop = true;
    }
}

消费者

public class Consumer implements Runnable {
    private Storage<String> storage;
    private volatile boolean breakLoop = false;

    public Consumer(Storage<String> storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        while (true) {
            if (breakLoop) {
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Consumer:" + storage.pop());
        }
    }

    public void destroy() {
        this.breakLoop = true;
    }
}

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。

public class Storage<T> {
    // 仓库最大存储量
    private final int MAX_SIZE = 1000;
    private int storageSize = 100;
    private Object[] data;
    private int top = 0;
    private Lock lock = new ReentrantLock();
    private Condition producerCon = lock.newCondition();
    private Condition consumerCon = lock.newCondition();

    public Storage(int size) {
        size = size <= 0 ? storageSize : size;
        size = size > this.MAX_SIZE ? this.MAX_SIZE : size;
        this.storageSize = size;
        data = new Object[this.storageSize];
    }

    public int getStorageSize() {
        return storageSize;
    }

    public T pop() throws InterruptedException {
        T t = null;
        lock.lock();
        try {

            while (top == 0) {
                //消费者等待
                consumerCon.await();
            }
            top--;
            t = (T) data[top];
            //唤醒生产者
            producerCon.signal();

        } finally {
            lock.unlock();
        }
        return t;
    }

    public void push(T t) throws InterruptedException {
        lock.lock();
        try {
            while (top == storageSize) {
                //生产者等待
                producerCon.await();
            }
            data[top++] = t;
            //唤醒消费者
            consumerCon.signal();
        } finally {
            lock.unlock();
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值