Case Analysis of Producer and Consumer in Java Thread Communication

  • 2021-11-13 01:51:59
  • OfStack

Related methods:
wait (): 1 Once this method is executed, the current thread goes into a blocking state and the synchronization monitor is released.
notify (): 1 Once this method is executed, one thread that is wait will be awakened, and if more than one thread is wait, the one with higher priority will be awakened.
notifyAll (): 1 Once this method is executed, all wait threads are awakened.
Description:
1. wait (), notify (), notifyAll () methods must be used in synchronization code blocks or synchronization methods.
2. The caller of wait (), notify (), notifyAll () methods must be a synchronization monitor in the synchronization code block or synchronization method.
Otherwise, an IllegalMonitorStateException exception occurs
3. wait (), notify (), and notifyAll () are defined in the java. lang. Object class.

Example of thread communication: Use two threads to print 1-100. Thread 1 and Thread 2 print alternately


class Number implements Runnable{
    private int number = 1;
    @Override
    public void run() {
        while(true){
            synchronized (this) {
                notify();
                if(number <= 100){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    try {
                        // So that the call is as follows wait() Method enters a blocking state 
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    break;
                }
            }
        }
    }
}
public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);
        t1.setName(" Thread 1");
        t2.setName(" Thread 2");
        t1.start();
        t2.start();
    }
}

Classic Example: Producer/Consumer Problem

The producer (Productor) gives the product to the shop assistant (Clerk), The consumer (Customer) takes the product from the clerk, and the clerk can only hold a fixed number of products at one time (such as: 20) If the producer tries to produce more products, the clerk will ask the producer to stop for 1 time, and then inform the producer to continue production if there is room for the products in the store. If there are no products in the store, the clerk will tell the consumer to wait for 1 time, and then inform the consumer to pick up the products if there are products in the store.

There are two possible problems here:

> When producers are faster than consumers, consumers will miss some data.

> When the consumer compares the producer block, the consumer will take the same data.

Analysis:

Is it a multithreading problem? Yes, producer thread, consumer thread
Is there any shared data? Yes, shop assistant (or product)
How to solve thread safety problems. Synchronization mechanism, there are three methods
Is threaded communication involved? Yes

class Clerk{
    private int productCount = 0;
    // To produce a product 
    public synchronized void produceProduct() {
        if(productCount < 20){
            productCount++;
            System.out.println(Thread.currentThread().getName() + ": Start production " + productCount + " Product ");
            notify();
        }else{
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    // Consumer products 
    public synchronized void consumeProduct() {
        if(productCount > 0){
            System.out.println(Thread.currentThread().getName() + ": Start consumption first " + productCount + " Product ");
            productCount--;
            notify();
        }else{
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Producer extends Thread{// Producer 
    private Clerk clerk;
    public Producer(Clerk clerk){
        this.clerk = clerk;
    }
    @Override
    public void run() {
        System.out.println(getName() + ": Start producing products .....");
        while(true){
            try {
                sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.produceProduct();
        }
    }
}
class Consumer extends Thread{// Consumer 
    private Clerk clerk;
    public Consumer(Clerk clerk){
        this.clerk = clerk;
    }
    @Override
    public void run() {
        System.out.println(getName() + ": Start consuming products .....");
        while(true){
            try {
                sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.consumeProduct();
        }
    }
}
public class ProductTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Producer p1 = new Producer(clerk);
        p1.setName(" Producer 1");
        Consumer c1 = new Consumer(clerk);
        c1.setName(" Consumer 1");
        Consumer c2 = new Consumer(clerk);
        c2.setName(" Consumer 2");
        p1.start();
        c1.start();
        c2.start();
    }
}

What are the similarities and differences between sleep () and wait ()?

1. The same point: 1 once the method is executed, the current thread can enter the blocking state.
2. Differences:

1) The position of the two method declarations is different, sleep () is declared in the Thread class, and wait () is declared in the Object class

2) The invocation has different requirements: sleep () can be invoked in any scenario where it is needed. wait () must be used in synchronization code blocks or synchronization methods

3) Regarding whether to release the synchronization monitor: If both methods are used in a synchronization code block or a synchronization method, sleep () does not release the lock, wait () does


Related articles: