第三章-線程之間的通訊-第二篇

生產者消費者模式

請看以下代碼安全

/**
 * @program: demo
 * @description: 生產者
 * @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的值是"+value);
                ValueObjec.value=value;
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: 消費者
 * @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的值是"+value);
                ValueObjec.value="";
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: 主線程
 * @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: 線程
 * @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: 線程
 * @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="";
}

輸出結果ide

....
get的值是1535543013723_95467291931143
set的值是1535543013723_95467291970255
get的值是1535543013723_95467291970255
set的值是1535543013723_95467292002650
get的值是1535543013723_95467292002650
set的值是1535543013723_95467292034255
get的值是1535543013723_95467292034255
set的值是1535543013723_95467292055588
get的值是1535543013723_95467292055588
set的值是1535543013723_95467292076526
get的值是1535543013723_95467292076526
set的值是1535543013723_95467292117612
...

多生產多消費

假死狀態就是線程進入waiting等待的狀態,若是所有線程都進入waiting裝填,則程序就不在執行任何業務功能了,整個項目處於停滯狀態。this

請看以下代碼線程

/**
 * @program: demo
 * @description: 消費者
 * @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("消費者" + Thread.currentThread().getName() + "*********進入等待*******");
                    lock.wait();
                }
                String value = ValueObjec.value;
                System.out.println("get的值是"+value);
                ValueObjec.value="";
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: 生產者
 * @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("生產者" + Thread.currentThread().getName() + "*********進入等待*******");
                    lock.wait();
                }
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                System.out.println("set的值是"+value);
                ValueObjec.value=value;
                lock.notify();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

/**
 * @program: demo
 * @description: 主線程
 * @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: 線程
 * @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: 線程
 * @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="";
}

這個多生產多消費的程序很不安全,由於notify方法只能保證一次喚醒一個程序,若是喚醒的程序不是異類程序而是同類程序,好比生產者喚醒生產者,若是一直這樣運行下去,可能會致使全部的程序都陷入等待狀態。code

假死解決辦法

解決假死的方法,當出現多生產多消費的時候,喚醒線程的時候喚醒全部的線程,即便用notifyAll方法,這樣就能保證不出現假死的狀況了。ip

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("消費者" + Thread.currentThread().getName() + "*********進入等待*******");
                    lock.wait();
                }
                String value = ValueObjec.value;
                System.out.println("get的值是"+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("生產者" + Thread.currentThread().getName() + "*********進入等待*******");
                    lock.wait();
                }
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                System.out.println("set的值是"+value);
                ValueObjec.value=value;
                lock.notifyAll();
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索