Chapter 3 - communication between threads - Chapter 2

Producer consumer model

See the following code

/**
 * @program: demo
 * @description: Producer
 * @author: lee
 * @create: 2018-08-29
 **/
public class Product {
    private String lock;

    public Product(String lock) {
        this.lock = lock;
    }

    public void setValue() {
        try {
            synchronized (lock) {
                if (!ValueObjec.value.equals("")) {
                    lock.wait();
                }
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                System.out.println("set The value is"+value);
                ValueObjec.value=value;
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: Consumer
 * @author: lee
 * @create: 2018-08-29
 **/
public class Consume {
    private String lock;
    public Consume() {
    }

    public Consume(String lock) {
        this.lock = lock;
    }
    public void  getValue() {
        try {
            synchronized (lock) {
                if (ValueObjec.value.equals("")) {
                    lock.wait();
                }
                String value = ValueObjec.value;
                System.out.println("get The value is"+value);
                ValueObjec.value="";
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: Main thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class Run {
    public static void main(String[] args) {
        String lock =  new String("");
        Thread thread = new Thread(new ThreadA(new Product(lock)));
        thread.start();
        Thread thread2 = new Thread(new ThreadB(new Consume(lock)));
        thread2.start();
    }
}    

/**
 * @program: demo
 * @description: thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class ThreadA implements Runnable {
    private Product product;

    public ThreadA(Product product) {
        this.product = product;
    }

    @Override
    public void run() {
        while (true) {
            product.setValue();
        }
    }
}

/**
 * @program: demo
 * @description: thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class ThreadB implements Runnable{
    private Consume consume;

    public ThreadB(Consume consume) {
        this.consume = consume;
    }

    @Override
    public void run() {
        while (true) {
            consume.getValue();
        }
    }
}

/**
 * @program: demo
 * @description: demo
 * @author: lee
 * @create: 2018-08-29
 **/
public class ValueObjec {
    public static String value="";
}    

Output result

....
The value of get is 1535543013723_
The value of set is 1535543013723_
The value of get is 1535543013723_
The value of set is 1535543013723_
The value of get is 1535543013723_
The value of set is 1535543013723_
The value of get is 1535543013723_
The value of set is 1535543013723_
The value of get is 1535543013723_
The value of set is 1535543013723_
The value of get is 1535543013723_
The value of set is 1535543013723_
...

More production and more consumption

The pseudo dead state is that the thread enters the waiting state. If all threads enter the waiting state, the program will not perform any business functions, and the whole project will be in a stagnant state.

See the following code

/**
 * @program: demo
 * @description: Consumer
 * @author: lee
 * @create: 2018-08-29
 **/
public class Consume {
    private String lock;
    public Consume() {
    }

    public Consume(String lock) {
        this.lock = lock;
    }
    public void  getValue() {
        try {
            synchronized (lock) {
                if (ValueObjec.value.equals("")) {
                    System.out.println("Consumer" + Thread.currentThread().getName() + "*********Enter wait*******");
                    lock.wait();
                }
                String value = ValueObjec.value;
                System.out.println("get The value is"+value);
                ValueObjec.value="";
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: Producer
 * @author: lee
 * @create: 2018-08-29
 **/
public class Product {
    private String lock;

    public Product(String lock) {
        this.lock = lock;
    }

    public void setValue() {
        try {
            synchronized (lock) {
                if (!ValueObjec.value.equals("")) {
                    System.out.println("Producer" + Thread.currentThread().getName() + "*********Enter wait*******");
                    lock.wait();
                }
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                System.out.println("set The value is"+value);
                ValueObjec.value=value;
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: Main thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class Run {
    public static void main(String[] args) {
        String lock = new String("");
        Thread thread = new Thread(new ThreadA(new Product(lock)));
        thread.start();
        Thread thread2 = new Thread(new ThreadA(new Product(lock)));
        thread2.start();
        Thread thread3 = new Thread(new ThreadA(new Product(lock)));
        thread3.start();
        Thread threadB = new Thread(new ThreadB(new Consume(lock)));
        threadB.start();
        Thread threadB1 = new Thread(new ThreadB(new Consume(lock)));
        threadB1.start();
        Thread threadB2 = new Thread(new ThreadB(new Consume(lock)));
        threadB2.start();
        Thread threadB3 = new Thread(new ThreadB(new Consume(lock)));
        threadB3.start();
    }
}    

/**
 * @program: demo
 * @description: thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class ThreadA implements Runnable {
    private Product product;

    public ThreadA(Product product) {
        this.product = product;
    }

    @Override
    public void run() {
        while (true) {
            product.setValue();
        }
    }
}

/**
 * @program: demo
 * @description: thread
 * @author: lee
 * @create: 2018-08-29
 **/
public class ThreadB implements Runnable{
    private Consume consume;

    public ThreadB(Consume consume) {
        this.consume = consume;
    }

    @Override
    public void run() {
        while (true) {
            consume.getValue();
        }
    }
}

/**
 * @program: demo
 * @description: demo
 * @author: lee
 * @create: 2018-08-29
 **/
public class ValueObjec {
    public static String value="";
}    

This multi production and multi consumption program is very unsafe, because the notify method can only guarantee to wake up one program at a time. If the wake-up program is not a heterogeneous program but a similar program, such as the producer wakes up the producer, if it continues to run like this, it may cause all programs to fall into a waiting state.

Feign death solution

To solve the problem of pseudo death, when there is more production and more consumption, all threads are awakened when the thread is awakened, that is, the notifyAll method is used, so that the situation of pseudo death can be avoided.

public class Consume {
    private String lock;
    public Consume() {
    }

    public Consume(String lock) {
        this.lock = lock;
    }
    public void  getValue() {
        try {
            synchronized (lock) {
                if (ValueObjec.value.equals("")) {
                    System.out.println("Consumer" + Thread.currentThread().getName() + "*********Enter wait*******");
                    lock.wait();
                }
                String value = ValueObjec.value;
                System.out.println("get The value is"+value);
                ValueObjec.value="";
                lock.notifyAll();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}


public class Product {
    private String lock;

    public Product(String lock) {
        this.lock = lock;
    }

    public void setValue() {
        try {
            synchronized (lock) {
                if (!ValueObjec.value.equals("")) {
                    System.out.println("Producer" + Thread.currentThread().getName() + "*********Enter wait*******");
                    lock.wait();
                }
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                System.out.println("set The value is"+value);
                ValueObjec.value=value;
                lock.notifyAll();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

Posted by cheeks2k on Mon, 06 Jan 2020 10:22:51 -0800