Production and consumption model - let you understand the thread state

Suppose you become the boss of Jingdong now, you will encounter a problem: in the case of limited warehouse capacity, control the storage of goods and send them out at the same time. How to control this situation? In java, we can use the production consumption model to complete.

The problem can be simplified as follows: the producer produces the goods and puts them in the warehouse, and the consumer takes the goods out of the warehouse

 

But we will also encounter some problems: the efficiency is too low, the judgment of the warehouse full and empty

Solution idea : use concurrency to improve efficiency, and use thread state to match the warehouse full and empty.

Now officially begins:

1. Create a warehouse class, and the member data is the quantity of goods.

2. Create a producer thread:

It is worth searching for the various states of the thread!

/**
                 * The thread waits for wait, that is, the thread does not have the right to operate, and it will not execute regardless of whether the cpu is allocated time. * The thread
                 wakes up notify, which means that the thread wakes up and obtains the right to operate. It can run as long as the cpu time is obtained.
                 * Use wait, notify Obtain the object monitor before, otherwise an IllegalMonitorStateException will be thrown
                 * wait() will immediately release the obj lock in synchronized (obj), so that other threads can execute obj.notify().
                 * But notify() will not immediately release the obj lock in sycronized (obj), it must wait for the thread where notify() is located to execute all the code in the synchronized (obj) block before releasing the lock.
                 * The reason why using lock can also release the lock, because ReentrantLock is written based on synchronized
                 */

public class Producer implements Runnable{
    //得到唯一仓库对象,方便上锁以及wait方法
    private Store store;
    public Producer(Store store){
        this.store = store;
    }
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            /**
             * 由于并发式操作,为了保证线程安全,需要使用“锁”
             * 但是,必须保证锁和wait作用于同一对象,不然会出现“死锁”现象
             */
            synchronized (store) {
                /**
                 * 线程等待wait,即线程没有操作权,无论cpu有无分配到时间都不会执行
                 * 线程唤醒notify,即将线程唤醒,获取操作权,只要得到cpu时间就可运行
                 * 使用wait,notify之前要获取对象监视器,不然会抛出IllegalMonitorStateException异常
                 * wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()。
                 * 但是notify()不会立刻立刻释放sycronized(obj)中的obj锁,必须要等notify()所在线程执行完synchronized(obj)块中的所有代码才会释放这把锁。
                 * 之所以用lock也可以释放锁,因为ReentrantLock是基于synchronized而所写的
                 */
                if (store.N >= 20){
                    try {
                        //得知仓库已满状态
                        System.out.println("仓库已满"+Thread.currentThread().getName()+"生产者进入等待状态");
                        store.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    //如果没有满,则开始生产
                    store.N++;
                    System.out.println(Thread.currentThread().getName() + "线程 正在生产数据...   " + store.N);
                    /**
                     * 开始唤醒生产者,进行生产,给消费者提供数据消费
                     * 同时保证了,生产消费可以一直进行下去。
                     */
                    store.notify();
                }
            }
        }
    }
}

3. Create a consumer thread:

The idea is consistent with the producer thread.

4. Start the thread in the warehouse:

 public void start(){
        Producer producer= new Producer(this);
        new Thread(producer).start();
        new Thread(producer).start();
        new Thread(producer).start();

        Consumer consumer = new Consumer(this);
        new Thread(consumer).start();
        new Thread(consumer).start();

    }
    public static void main(String[] args) {
        Store ss = new Store();
        ss.start();
    }

operation result:

 

Guess you like

Origin blog.csdn.net/AkinanCZ/article/details/126917750