Java-线程(生产者消费者模式)

22 篇文章 0 订阅

普通的生产者消费者模式:

package ss;

/**
 * 线程通讯实例:
 * 
 * 生产者消费者模式
 * 
 */

//产品类
class Product{

    String name;//名字

    double price;//价格

    boolean flag=false;//产品是否生产完毕的标签,默认情况是没有生产完成。

}

//生产者
class Producer extends Thread{
    //产品
    Product p;

    public Producer(Product p){
        this.p=p;
    }
@Override
public void run() {

    int i=0;
    while(true){
        synchronized (p) {
            if(p.flag==false){
                if(i%2==0){
                    p.name="苹果";
                    p.price=6.5;
                }else{
                    p.name="香蕉";
                    p.price=2.0;
                }
                System.out.println("生产者生产出了: "+p.name+"价格是: "+p.price);
                p.flag=true;
                i++;
                p.notifyAll();//唤醒消费者去消费
            }else{
                //已经生产完毕,等待消费者先去消费
                try {
                    p.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

}


//消费者
class Customer extends Thread{

    Product p;

    public Customer(Product p){
        this.p=p;
    }
    @Override
    public void run() {

        while(true){
            synchronized (p) {
                if(p.flag==true){//产品已经生产完毕
                    System.out.println("消费者消费了"+p.name+"价格: "+p.price);
                    p.flag=false;
                    p.notifyAll();//唤醒生产者去生产

                }else{
                    //产品还有生产,等待生产者先生产
                    try {
                        p.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            }

        }


    }

}



public class Demo {
    public static void main(String[] args) {
        Product p=new Product();//产品
        //创建生产者
        Producer producer=new Producer(p);
        //创建消费
        Customer customer=new Customer(p);
        //调用start方法开启线程

        producer.start();
        customer.start();
    }


}

队列实现生产者消费者模式:

  • 在Java多线程应用中,队列的使用率很高,多数生产者消费者模型的首选数据结构就是队列(先进先出)。
  • Java提供线程安全的Queue可以分为阻塞式队列和非阻塞式队列
  • 阻塞式队列的典型例子就是BlockingQueue.当前线程没有数据或者数据满了的时候会阻塞。
  • 非阻塞式队列的典型例子就是LinkedList(双向列表)
/***
 * Collection(list,set,queue)
 * @author pjy
 * 
 * LinkedList是一个Deque(双重队列)入口可以添加数据,入口也可以移除数据
 */
public class ThreadCommunictaion01 {

    public static void main(String[] args)
    throws Exception{
        List<String> list=
        new ArrayList<String>(2);
        list.add("a1");
        list.add("a2");
        list.add("a3");
        list.add("a4");
        System.out.println("list.size()="+list.size());

        //阻塞式队列
        final BlockingQueue<String> q1=
        new ArrayBlockingQueue<>(3);

        new Thread(){
            public void run(){
             try{
              String s=q1.take();//阻塞式方法,没有数据则等待
             //String s=q1.remove();//没有数据会抛出异常
              System.out.println("s="+s);
              }catch(Exception e){
              e.printStackTrace();
             }
            };
        }.start();
        q1.put("A");
        q1.put("B");
        q1.put("C");
        //当队列满以后,当前线程会阻塞
        q1.put("D");//此方法满了会阻塞
        //q1.add("A");此方法满了会抛出异常
        System.out.println("q1.size()="+q1.size());

    }
}

案例:简单的生产者消费者模式:一边放,一边取

  • BlockingQueue队列:

import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 *
 * 生产者:向容器放数据,此容器从键盘读入字符串
 * 存储到容器(阻塞式队列)中
 *
 */
class Producer extends Thread{//is a
    //has a (关联)
    private BlockingQueue<String> queue;
    public Producer(BlockingQueue<String> queue) {
        this.queue=queue;
    }
    @Override
    public void run() {
        Scanner sc=new Scanner(System.in);
        while(true){
            //从键盘读入一个字符串
            System.out.println("放数据:");
            String s=sc.nextLine();
            try{
            //将字符串放入容器
            queue.put(s);
            }catch(Exception e){e.printStackTrace();}
        }
    }
}  
/**消费者:从容器中取数据*/
class Consumer extends Thread{
    //has a (关联)
    private BlockingQueue<String> queue;
    public Consumer(BlockingQueue<String> queue) {
        this.queue=queue;
    }
    @Override
    public void run() {
        while(true){
          try{
          System.out.println("take:"+queue.take());
          }catch(Exception e){e.printStackTrace();}
        }
    }
}
public class ThreadCommunication02 {

    public static void main(String[] args) {
        //容器
        BlockingQueue<String> container=new LinkedBlockingQueue<String>(3); 
        //构建线程对象
        Producer p=new Producer(container);
        Consumer c=new Consumer(container);
            //启动线程
            p.start();
            c.start();
            //一边放一边取(简单地生产者消费者模式)
    }
}
  • LinkedList队列:

import java.util.LinkedList;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;

/**生产者向容器放数据,此容器从键盘读入字符串
 * 存储到容器(非阻塞式队列)中*/
class Producer02 extends Thread{//is a
    //has a (关联)
    private LinkedList<String> queue;
    public Producer02(LinkedList<String> queue) {
        this.queue=queue;
    }
    @Override
    public void run() {
        Scanner sc=new Scanner(System.in);
        while(true){
            //从键盘读入一个字符串
            System.out.println("放数据:");
            String s=sc.nextLine();//阻塞方法
            synchronized (this) {
             try{
             //将字符串放入容器
             queue.addLast(s);
             //通知消费者取
             queue.notify();
             }catch(Exception e){e.printStackTrace();}
            }
        }
    }
}
/**消费者从容器中取数据*/
class Consumer02 extends Thread{
    //has a (关联)
    private LinkedList<String> queue;
    public Consumer02(LinkedList<String> queue) {
        this.queue=queue;
    }
    @Override
    public void run() {
        while(true){
          synchronized (this) {
           //容器内容为空时则等待
           if(queue.size()==0)try{queue.wait();}catch(Exception e){}
           //取数据
           try{
           System.out.println("take:"+queue.removeFirst());
           }catch(Exception e){e.printStackTrace();}
           //通知消费者继续方法
           //queue.notify();
          }
        }
    }
}
public class ThreadCommunication03 {

    public static void main(String[] args) {
        //容器
        LinkedList<String> container=
        new LinkedList<String>(); 
        //构建线程对象
        Producer02 p=new Producer02(container);
        Consumer02 c=new Consumer02(container);
        //启动线程
        p.start();
        c.start();
    }
}
  • ArrayList:
class Producer03 extends Thread{
    @Override
    public void run() {
        Scanner sc=new Scanner(System.in);
        while(true){
         String data=sc.nextLine();
         //放数据

        }
    }
}
class Consumer03 extends Thread{
    @Override
    public void run() {
        while(true){
          //取数据
        }
    }
}
class Container03{
    private List<String> list;
    /**@param 容量*/
    public Container03(int cap) {
        list=new ArrayList<>(cap);
    }
    /**放数据*/
    public synchronized void put(String data){
       //1.判断容器是否已满,满则等待
       //2.放数据
       //3.通知消费者取数据
    }
    /**取数据*/
    public synchronized void take(){
       //1.判断容器是否为空,空则等待
       //2.取数据
       //3.通知生产者放数据
    }
}

public class ThreadCommunication04 {

}

wait()与notify()

wait():
等待,如果线程执行了wait方法,那么该线程会进入等待的状态,等待状态下的线程必须要被其他线程调用notify方法才能唤醒。

一个线程如果执行了wait方法,那么该线程就会进去一个以锁对象为标识符的线程池中等待。

notify():
唤醒 唤醒等待的方法。

如果一个线程执行了notify方法,那么会唤醒以锁对象为标识符中等待线程中其中一个。

wait与notify方法要注意的事项:
1、wait方法与notify方法是属于Object对象的。
2、wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用。
3、wait方法与notify方法必须要由锁对象调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值