线程间的通信(Object类的wait(),notify(),notifyAll())

Object类提供了wait(),notify(),notifyAll()方法用于线程间的通信

  • void wait(),当前线程进入WAITING状态,直到其他线程调用notify()或者notifyAll()唤醒该线程
  • void wait(long timeout),当前线程进入TIMED_WAITING状态,直到其他线程调用nofity()或者notifyAll()唤醒,或等待超过指定的时间
  • void wait(long timeout, int nanos),当前线程进入TIMED_WAITING状态,直到其他线程调用nofity()或者notifyAll()唤醒,或等待超过指定的时间,或某个线程中断当前线程。该方法指定了一个纳秒
  • void notify(),唤醒一个等待改线程的线程
  • void notify(),唤醒所有等待改线程的线程

典型的生产者消费者模型实现了线程间的通信

信号灯法实现生产者消费者模型

代码实现

// 定义一个产品
class Product {
    private int id; // 产品id

    public Product(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

// 定义一个生产平台
class Client {
    private Product product;
    private boolean flag = true; // 标记位,true可生产,false可消费

    public synchronized void add(Product product) {
        if (!this.flag) {
            // 已经有产品,等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 如果没有产品,生产
        this.product = product;
        // 修改标记可消费
        this.flag = false;
        // 通知消费者
        this.notifyAll();
    }

    public synchronized Product get() {
        if (this.flag) {
            // 等待生产者生产
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.flag = true;
        this.notifyAll();
        return this.product;
    }
}

// 定义一个生产者
class producer extends Thread {
    private Client client;

    public producer(Client client) {
        this.client = client;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            this.client.add(new Product(i));
            System.out.println("生产产品 --> " + i);
        }
    }
}

// 定义一个消费者
class Consumer extends Thread {
    private Client client;

    public Consumer(Client client) {
        this.client = client;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            Product product = this.client.get();
            System.out.println("消费产品 --> " + product.getId());
        }
    }
}

测试代码

Client client = new Client();
new producer(client).start();
new Consumer(client).start();

运行结果

生产产品 --> 0
消费产品 --> 0
生产产品 --> 1
消费产品 --> 1
生产产品 --> 2
消费产品 --> 2
生产产品 --> 3
消费产品 --> 3
生产产品 --> 4
消费产品 --> 4
生产产品 --> 5
消费产品 --> 5
生产产品 --> 6
消费产品 --> 6
生产产品 --> 7
消费产品 --> 7
生产产品 --> 8
消费产品 --> 8
生产产品 --> 9
消费产品 --> 9
管程法实现生产者消费者模型

代码实现

// 定义一个产品
class Product {
    private int id; // 产品的id

    public Product(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

// 定义一个容器存放产品
class Container {
    // 暂时存放产品
    private List<Product> list = new ArrayList<>(10);
    // 当前产品数量
    private int count = 0;

    // 生产
    public synchronized void push(Product product) {
        // 如果list满了,生产者等待
        if (this.count == 9) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 否则生产
        this.list.add(product);
        this.count++;
        this.notifyAll();
    }

    // 消费
    public synchronized Product pop() {
        // 如果没有产品,等待,并通知生产者生产
        if (this.count == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Product product = this.list.remove(0);
        this.count--;
        this.notifyAll();
        return product;
    }
}

// 定义一个生产者
class Producer extends Thread {
    private Container container;

    public Producer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            container.push(new Product(i));
            System.out.println("生产产品 --> " + i);
        }
    }
}

// 定义一个消费者
class Consumer extends Thread {
    private Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            Product product = container.pop();
            System.out.println("消费产品 --> " + product.getId());
        }
    }
}

测试代码

Container container = new Container();

new Producer(container).start();
new Consumer(container).start();

运行结果

生产产品 --> 0
生产产品 --> 1
生产产品 --> 2
生产产品 --> 3
消费产品 --> 0
生产产品 --> 4
生产产品 --> 5
生产产品 --> 6
生产产品 --> 7
生产产品 --> 8
生产产品 --> 9
消费产品 --> 1
消费产品 --> 2
消费产品 --> 3
消费产品 --> 4
消费产品 --> 5
消费产品 --> 6
消费产品 --> 7
消费产品 --> 8
消费产品 --> 9
消费产品 --> 10
生产产品 --> 10
生产产品 --> 11
生产产品 --> 12
生产产品 --> 13
生产产品 --> 14
生产产品 --> 15
生产产品 --> 16
生产产品 --> 17
生产产品 --> 18
生产产品 --> 19
消费产品 --> 11
消费产品 --> 12
消费产品 --> 13
消费产品 --> 14
消费产品 --> 15
消费产品 --> 16
消费产品 --> 17
消费产品 --> 18
消费产品 --> 19
上一篇:随手练——HDU 1251 统计难题


下一篇:2020-09-10:java里Object类有哪些方法?