javaSE高级开发多线程——6 生产者与消费者模型

sychonized:是为了多线程资源共享同步
ThreadLocal:是为了多线程资源独占式
1.生产消费者模型
在这里插入图片描述
我们最理想的模型是生产者和消费者的速度匹配。
2.通知的使用
在正式进入生产者和消费者模型之前我们先做一些准备基础。在生产者消费者里面最核心的就是通知和等待,下面我们将看看用什么样的方法可以是实现等待或者通知。
(1) 等待:wait()
其实wait()方法就是使线程停止运行。在同步代码块中使用。
(2) 通知:notify() :通知一个线程
           notifyAll(): 通知所有线程
它们都在同步代码块中使用。

package com.wschase.shengchanzhexiaofeizhe;

import org.omg.PortableServer.THREAD_POLICY_ID;

/**
 * Author:WSChase
 * Created:2019/1/13
 */
public class TestNotifyAll {
    public static void main(String[] args) {
        Object object=new Object();
        new Thread(new MyRunnable(true,object),"生产者A").start();
        new Thread(new MyRunnable(true,object),"生产者B").start();
        new Thread(new MyRunnable(true,object),"生产者C").start();
        new Thread(new MyRunnable(false,object),"消费者A").start();
        new Thread(new MyRunnable(false,object),"消费者B").start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
class MyRunnable implements Runnable{

    //如果是true表示生产者
    //如果是false表示消费者
    private final boolean flag;

    private final Object object;

    /**
     *
     * @param flag  表示生产者还是消费者
     * @param object 表示资源(锁)
     */

    MyRunnable(boolean flag,Object object) {
        this.flag = flag;
        this.object=object;
    }

    @Override
    public void run() {
        if(flag){
            this.waitMethod();
        }else{
            this.notifyMethod();
        }
    }

    //消费者通知
    private void notifyMethod() {
        synchronized (object){
            String name=Thread.currentThread().getName();
            System.out.println(name+"消费者开始");
            this.object.notifyAll();//给所有等待的线程通知
            System.out.println(name+"消费者结束");
        }
    }

    //生产者等待
    private void waitMethod() {
        synchronized (object) {
            while (true) {
                String name=Thread.currentThread().getName();
                System.out.println(name+"生产者开始");
                try {
                    this.object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name+"生产者结束");
            }
        }
    }
}

3.生产者与消费者模型
(1)出现阻塞的5种情况(记住)
1)线程调用sleep()方法,主动放弃占用的处理器资源。
2)线程调用了阻塞式IO方法,在该方法返回前,该线程被阻塞。
3)线程视图获得一个同步监视器,但该同步监视器正被其他线程所持有。
4)线程等待某个通知。
5)程序调用了suspend方法将该线程挂起。此方法容易导致死锁,尽量避免使用该方法。
run()方法运行结束后进入销毁阶段,整个线程执行完毕。
(2)生产者消费者模型
1)一个生产者一个消费者并且只生产一次

package com.wschase.shengchanzhexiaofeizhe;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

/**生产者消费者模型
 * Author:WSChase
 * Created:2019/1/13
 */
public class ProducerCustomer {

    public static void main(String[] args) {
        Queue<Goods> queue=new LinkedList<>();
        AtomicInteger goodsName=new AtomicInteger(1);//自增长是商品的name的编号
        Object monitor=new Object();//监听器--监听器都是Object类
        Producer producer=new Producer(queue,monitor,goodsName);
        Customer customer=new Customer(queue,monitor);
        new Thread(producer).start();
        new Thread(customer).start();
    }

}

//商品
class Goods{
    private final String name;

    Goods(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                '}';
    }
}

//生产者
class Producer implements Runnable{
//需要把商品放到生产者里面,所以它需要有一个集合
    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器-->作为锁来处理

    private final AtomicInteger atomicInteger;//自增长
    Producer(Queue<Goods> goods, Object monitor, AtomicInteger atomicInteger) {
        this.goods = goods;
        this.monitor = monitor;
        this.atomicInteger = atomicInteger;
    }


    @Override
    public void run() {
        synchronized (monitor){
            //商品池满了,所以需要等待
            if(this.goods.size()==10){//如果等于10表示已经满了
                try {
                    this.monitor.wait();//
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                //这个表示商品池没有满的时候,需要生产者生产商品,每次加1表示每次生产一个
                this.goods.add(new Goods(String.valueOf(atomicInteger.getAndAdd(1))));
            }
        }
    }
}


//消费者
class Customer implements Runnable{

    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器

    Customer(Queue<Goods> goods, Object monitor) {
        this.goods = goods;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        synchronized (monitor){
            if(this.goods.isEmpty()){
                //如果是空的就通知
                this.monitor.notifyAll();
            }else {
                //如果不是空的就取一个,消费张品
                Goods goods=this.goods.poll();

                System.out.println(goods);
            }
        }

    }
}

2)一个生产者一个消费者并且生产消费多次

package com.wschase.shengchanzhexiaofeizhe;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

/**生产者消费者模型
 * Author:WSChase
 * Created:2019/1/13
 */
public class ProducerCustomer {

    public static void main(String[] args) {
        Queue<Goods> queue=new LinkedList<>();
        AtomicInteger goodsName=new AtomicInteger(1);//自增长是商品的name的编号
        Object monitor=new Object();//监听器--监听器都是Object类
        Producer producer=new Producer(queue,monitor,goodsName);
        Customer customer=new Customer(queue,monitor);
        new Thread(producer).start();
        new Thread(customer).start();
    }

}

//商品
class Goods{
    private final String name;

    Goods(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                '}';
    }
}

//生产者
class Producer implements Runnable{
//需要把商品放到生产者里面,所以它需要有一个集合
    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器-->作为锁来处理

    private final AtomicInteger atomicInteger;//自增长
    Producer(Queue<Goods> goods, Object monitor, AtomicInteger atomicInteger) {
        this.goods = goods;
        this.monitor = monitor;
        this.atomicInteger = atomicInteger;
    }


    @Override
    public void run() {
        while (true){

        synchronized (monitor){
            //商品池满了,所以需要等待
            if(this.goods.size()==10){//如果等于10表示已经满了
                try {
                    this.monitor.wait();//
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                //这个表示商品池没有满的时候,需要生产者生产商品,每次加1表示每次生产一个
                Goods goods=new Goods(String.valueOf(atomicInteger.getAndAdd(1)));
                this.goods.add(goods);
                System.out.println("生产者生产"+goods);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
        }
}


//消费者
class Customer implements Runnable{

    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器

    Customer(Queue<Goods> goods, Object monitor) {
        this.goods = goods;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        while (true){

        synchronized (monitor){
            if(this.goods.isEmpty()){
                //如果是空的就通知
                this.monitor.notifyAll();
            }else {
                //如果不是空的就取一个,消费张品
                Goods goods=this.goods.poll();

                System.out.println("消费者消费"+goods);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
        }
}

3)多个生产者

package com.wschase.shengchanzhexiaofeizhe;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

/**生产者消费者模型
 * Author:WSChase
 * Created:2019/1/13
 */
public class ProducerCustomer {

    public static void main(String[] args) {
        Queue<Goods> queue=new LinkedList<>();
        AtomicInteger goodsName=new AtomicInteger(1);//自增长是商品的name的编号
        Object monitor=new Object();//监听器--监听器都是Object类
        Producer producer1=new Producer(queue,monitor,goodsName);
        Producer producer2=new Producer(queue,monitor,goodsName);
        Customer customer1=new Customer(queue,monitor);
        new Thread(producer1,"生产者1").start();
        new Thread(producer2,"生产者2").start();
        new Thread(customer1).start();
    }

}

//商品
class Goods{
    private final String name;

    Goods(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                '}';
    }
}

//生产者
class Producer implements Runnable{
//需要把商品放到生产者里面,所以它需要有一个集合
    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器-->作为锁来处理

    private final AtomicInteger atomicInteger;//自增长
    Producer(Queue<Goods> goods, Object monitor, AtomicInteger atomicInteger) {
        this.goods = goods;
        this.monitor = monitor;
        this.atomicInteger = atomicInteger;
    }


    @Override
    public void run() {
        while (true){

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        synchronized (monitor){
            //商品池满了,所以需要等待
            if(this.goods.size()==10){//如果等于10表示已经满了
                try {
                    this.monitor.wait();//
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                //这个表示商品池没有满的时候,需要生产者生产商品,每次加1表示每次生产一个
                Goods goods=new Goods(String.valueOf(atomicInteger.getAndAdd(1)));
                this.goods.add(goods);
                System.out.println(Thread.currentThread().getName()+"生产"+goods);//打印出谁生产的
            }
        }
    }
        }
}


//消费者
class Customer implements Runnable{

    private final Queue<Goods> goods;//注意在这个地方我们一定不能new,因为我们需要实现共享,需要传入进来

    private final Object monitor;//监听器

    Customer(Queue<Goods> goods, Object monitor) {
        this.goods = goods;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        while (true){

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        synchronized (monitor){
            if(this.goods.isEmpty()){
                //如果是空的就通知
                this.monitor.notifyAll();
            }else {
                //如果不是空的就取一个,消费张品
                Goods goods=this.goods.poll();

                System.out.println("消费者消费"+goods);
            }
        }

    }
        }
}

注意:我们将休眠sleep加在不同的位置,最后结果出现的生产消费将会不同。

猜你喜欢

转载自blog.csdn.net/ZhuiZhuDream5/article/details/86419710