浅谈Java简单实现的生产者与消费者问题

Posted 离愁i

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Java简单实现的生产者与消费者问题相关的知识,希望对你有一定的参考价值。

一、面对生产者和消费者的问题,首先我们得明白几点

生产者:生产数据;
消费者:消费数据。
消费者在没有数据可供消费的情况下,不能消费;
生产者在原数据没有被消费掉的情况下,不能生产新数据。
假设,数据空间只有一个。
实际上,如果实现了正确的生产和消费,则,两个线程应该是严格的交替执行。

synchronized关键字若用在代码中,形成一个同步块,且,必须要执行锁:
    synchronized (锁对象) {
        同步块
    }
同步块使得锁对象称为thread monitor
二、代码实现:

1.首先我们建立一个生产者和消费者共同拥有的锁的类:

1 package com.mec.about_procuder_customer.core;
2 
3 public class ProcuderCustomer {
4     //初始状态的数据为0个
5     protected static volatile int count = 0;
6     //执行锁
7     protected final static Object lock = new Object();
8 }

上述代码有一个关键字volatile,它是保证线程之间有序的一种方式,最重要也是最直接的是禁止寄存器优化。就是如果线程run方法中只是一个循环,并没有执行语句,那么,这个线程将不会执行。

2.我们再来建立一个生产者的类:

 

 1 package com.mec.about_procuder_customer.core;
 2 
 3 //生产者
 4 public class Procuder extends ProcuderCustomer implements Runnable {
 5     
 6     //存放数据的空间
 7     private int[] dataSpace;
 8     
 9     public Procuder(int[] dataSpace, String threadName) {
10         this.dataSpace = dataSpace;
11         //启动线程
12         new Thread(this, threadName).start();
13     }
14     
15     @Override
16     public void run() {
17         int i = 0;
18         
19         while (true) {
20             synchronized (lock) {
21                 //判断是否空间已满
22                 if (count < dataSpace.length) {
23                     //产生者放数据
24                     dataSpace[count] = i++;
25                     System.out.println("[" + Thread.currentThread().getName()
26                             + "]线程生产了一个数:" + dataSpace[count++]
27                             + " " + count);
28                     try {
29                         //只是为了看的清楚,沉睡2秒
30                         Thread.sleep(200);
31                     } catch (InterruptedException e) {
32                         e.printStackTrace();
33                     }
34                     //唤醒消费者
35                     lock.notify();
36                 } else {
37                     try {
38                         //使自己处于阻塞状态
39                         lock.wait();
40                     } catch (InterruptedException e) {
41                     e.printStackTrace();
42                     }
43                 }
44             }
45         }
46     }
47 }

 

3.建立消费者的类:

 1 package com.mec.about_procuder_customer.core;
 2 
 3 //消费者
 4 public class Customer extends ProcuderCustomer implements Runnable {
 5     //存放数据的空间
 6     private int[] dataSpace;
 7     
 8     public Customer(int[] dataSpace, String threadName) {
 9         this.dataSpace = dataSpace;
10         //启动线程
11         new Thread(this, threadName).start();
12     }
13     
14     @Override
15     public void run() {
16         while (true) {
17             //加锁
18             synchronized (lock) {
19                 //判断是否有数据
20                 if (count > 0) {
21                     System.out.println("[" + Thread.currentThread().getName()
22                             + "]线程消费了一个数:" + dataSpace[--count]);
23                     //唤醒生产者
24                     lock.notifyAll();
25                 } else {
26                     try {
27                         //使自己处于阻塞状态
28                         lock.wait();
29                     } catch (InterruptedException e) {
30                         e.printStackTrace();
31                     }
32                 }
33             }
34         }
35     }
36 
37 }

4.测试类

 1 package com.mec.about_procuder_customer.test;
 2 
 3 import com.mec.about_procuder_customer.core.Customer;
 4 import com.mec.about_procuder_customer.core.Procuder;
 5 
 6 public class Test {
 7 
 8     public static void main(String[] args) {
 9         int[] data = new int[10];
10         new Procuder(data, "生产者1");
11         new Procuder(data, "生产者2");
12         new Customer(data, "消费者");
13     }
14 
15 }

运行结果:

 

以上是关于浅谈Java简单实现的生产者与消费者问题的主要内容,如果未能解决你的问题,请参考以下文章

生产者与消费者 代码实现 java

java实现生产者和消费者问题的几种方式

浅谈三种使用Redis实现MQ的方式

Java多线程-Lock锁的使用,以及生产者和消费者的实现

Java实现多线程生产者消费模型及优化方案

Java生产消费者模型——代码解析