[Java concurrent programming practice] -- "J. U. C": Condition, j. u. ccondition

Source: Internet
Author: User

[Java concurrent programming practice] -- "J. U. C": Condition, j. u. ccondition

Before reading Condition, let's take a look at the following example:

Factory type, used to store and retrieve goods:

Public class Depot {private int depotSize; // repository size private Lock lock; // exclusive lock public Depot () {depotSize = 0; Lock = new ReentrantLock ();} /*** warehouse receiving ** @ param value */public void put (int value) {try {lock. lock (); depotSize + = value; System. out. println (Thread. currentThread (). getName () + "put" + value + "----> the depotSize:" + depotSize);} finally {lock. unlock () ;}/ *** goods warehouse picking * @ param value */public void get (int value) {try {lock. lock (); depotSize-= value; System. out. println (Thread. currentThread (). getName () + "get" + value + "----> the depotSize:" + depotSize);} finally {lock. unlock ();}}}

Producer, production product, add product to warehouse:

public class Producer {    private Depot depot;        public Producer(Depot depot){        this.depot = depot;    }        public void produce(final int value){        new Thread(){            public void run(){                depot.put(value);            }        }.start();    }}

Consumers consume goods and take the goods from the warehouse:

public class Customer {    private Depot depot;        public Customer(Depot depot){        this.depot = depot;    }        public void consume(final int value){        new Thread(){            public void run(){                depot.get(value);            }        }.start();    }}

Test class:

public class Test {    public static void main(String[] args) {        Depot depot = new Depot();                Producer producer = new Producer(depot);        Customer customer = new Customer(depot);                producer.produce(10);        customer.consume(5);        producer.produce(20);        producer.produce(5);        customer.consume(35);    }}

Running result:

Thread-0 put 10 ----> the depotSize: 10Thread-1 get 5 ----> the depotSize: 5Thread-2 put 20 ----> the depotSize: 25Thread-3 put 5 ----> the depotSize: 30Thread-4 get 35 ----> the depotSize: -5

There is no error in the running result of the program. First put10, then get5, put20, put5, and get35. The program running result is very correct, but in real life, this instance has two errors:

First, the warehouse capacity is limited. We cannot add goods to the warehouse without limit.

Second, the warehouse capacity cannot be negative, but the final result is-5, which is in conflict with reality.

How to solve the above two errors? This is the turn of Condition.

Condition

Through the previous blogs, we know that Lock provides a more powerful and flexible Lock mechanism than synchronized. To some extent, it replaces synchronized. Condition is literally a Condition. For a thread, it provides a meaning for the thread so that the thread is suspended until another thread in a certain state (Condition) may be true to notify it.

For Condition, jdk api explains this as follows:

Condition splits the Object monitor methods (wait, policy, and policyall) into distinct objects so that they can be combined with any Lock implementation, multiple waiting sets (wait-set) are provided for each object ). Here, Lock replaces the use of synchronized methods and statements, and Condition replaces the use of Object monitor methods.

A condition (also known as a condition queue or condition variable) provides a meaning for the thread so that before another thread in a certain state condition may be true now, always suspend the thread (that is, let it "wait "). Because access to this shared state information occurs in different threads, it must be protected, so some form of lock should be associated with this condition. The main attribute of waiting to provide a condition is to release the related lock in an atomic way and suspend the current thread, as the Object. wait does.

The Condition instance is essentially bound to a lock. To obtain a Condition instance for a specific Lock instance, use its newCondition () method. Below we solve the above problem through Condition: Here we only change the repository Depot code:

Public class Depot {private int depotSize; // repository size private Lock lock; // exclusive Lock private int capaity; // repository capacity private Condition fullCondition; private Condition emptyCondition; public Depot () {this. depotSize = 0; this. lock = new ReentrantLock (); this. capaity = 15; this. fullCondition = lock. newCondition (); this. emptyCondition = lock. newCondition ();}/*** goods warehouse receiving * @ param value */public void put (int value) {Lock. lock (); try {int left = value; while (left> 0) {// when the stock is full, "producer" waits for "consumer" to consume while (depotSize> = capaity) {fullCondition. await () ;}// obtain the actual warehouse receiving quantity: estimated inventory (existing inventory in the warehouse + production quantity)> warehouse capacity? Warehouse capacity-existing warehouse inventory: production quantity // depotSize left capaity-depotSize left int inc = depotSize + left> capaity? Capaity-depotSize: left; depotSize + = inc; left-= inc; System. out. println (Thread. currentThread (). getName () + "---- Number of warehouse receiving:" + value + "; actual number of warehouse receiving:" + inc + "; number of warehouse goods:" + depotSize + ";; no warehouse receiving quantity: "+ left); // notifies the consumer that emptyCondition can be consumed. signal () ;}} catch (InterruptedException e) {} finally {lock. unlock () ;}/ *** goods warehouse picking * @ param value */public void get (int value) {lock. lock (); try {int left = value; While (left> 0) {// The warehouse is empty. The "consumer" waits for the "producer" to produce the goods while (depotSize <= 0) {emptyCondition. await () ;}// actual consumption warehouse inventory quantity <quantity to be consumed? Warehouse inventory quantity: quantity to be consumed int dec = depotSize <left? DepotSize: left; depotSize-= dec; left-= dec; System. out. println (Thread. currentThread (). getName () + "---- quantity to be consumed:" + value + "; actual consumption quantity:" + dec + "; existing warehouse quantity: "+ depotSize +"; how many items are not consumed: "+ left); // notify the producer that fullCondition can be produced. signal () ;}} catch (InterruptedException e) {e. printStackTrace ();} finally {lock. unlock ();}}}

Test:

public class Test {    public static void main(String[] args) {        Depot depot = new Depot();                Producer producer = new Producer(depot);        Customer customer = new Customer(depot);                producer.produce(10);        customer.consume(5);        producer.produce(15);        customer.consume(10);        customer.consume(15);        producer.produce(10);    }}

Running result:

Thread-0 ---- warehouse receiving quantity: 10; actual warehouse receiving quantity: 10; warehouse receiving quantity: 10; no warehouse receiving quantity: 0Thread-1 ---- consumption quantity: 5 ;; actual consumption quantity: 5; existing warehouse quantity: 5; number of items not consumed: 0 thread-4-quantity to be consumed: 15; actual consumption quantity: 5 ;; existing warehouse quantity: 0; how many items are not consumed: 10Thread-2 ---- Number of warehouse receiving: 15; actual number of warehouse receiving: 15; number of warehouse receiving goods: 15 ;; no warehouse receiving quantity: 0Thread-4 ---- quantity to be consumed: 15; actual consumption quantity: 10; existing warehouse quantity: 5; how many items are not consumed: 0Thread-5 ---- warehouse receiving quantity: 10; actual warehouse receiving quantity: 10; warehouse receiving quantity: 15; no warehouse receiving quantity: 0Thread-3 ---- consumption quantity: 10 ;; actual consumption quantity: 10; existing warehouse quantity: 5; number of items not consumed: 0

In Condition, we use await () to replace wait (), signal () to replace policy (), and signalAll () to replace policyall (). For our previous use of the traditional Object method, condition can be implemented.

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.