第三章-线程之间的通信-第二篇

博客围绕Python的生产者消费者模式展开,介绍了多生产多消费情况。指出假死状态是线程进入waiting等待,若全部线程如此,程序会停滞。多生产多消费程序不安全,notify方法可能致所有程序等待,解决办法是用notifyAll方法唤醒所有线程。

生产者消费者模式

请看如下代码

/**
 * @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="";
}    

输出结果

....
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装填,则程序就不在执行任何业务功能了,整个项目处于停滞状态。

请看如下代码

/**
 * @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方法只能保证一次唤醒一个程序,如果唤醒的程序不是异类程序而是同类程序,比如生产者唤醒生产者,如果一直这样运行下去,可能会导致所有的程序都陷入等待状态。

假死解决办法

解决假死的方法,当出现多生产多消费的时候,唤醒线程的时候唤醒所有的线程,即使用notifyAll方法,这样就能保证不出现假死的情况了。

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();
        }
    }
}

转载于:https://my.oschina.net/jiansin/blog/1936206

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值