一、面对生产者和消费者的问题,首先我们得明白几点:
生产者:生产数据;
消费者:消费数据。
消费者在没有数据可供消费的情况下,不能消费;
生产者在原数据没有被消费掉的情况下,不能生产新数据。
假设,数据空间只有一个。
实际上,如果实现了正确的生产和消费,则,两个线程应该是严格的交替执行。
synchronized关键字若用在代码中,形成一个同步块,且,必须要执行锁:
synchronized (锁对象) {
同步块
}
同步块使得锁对象称为thread monitor
二、代码实现:
1.首先我们建立一个生产者和消费者共同拥有的锁的类:
package com.mec.about_procuder_customer.core; public class ProcuderCustomer {
//初始状态的数据为0个
protected static volatile int count = 0;
//执行锁
protected final static Object lock = new Object();
}
上述代码有一个关键字volatile,它是保证线程之间有序的一种方式,最重要也是最直接的是禁止寄存器优化。就是如果线程run方法中只是一个循环,并没有执行语句,那么,这个线程将不会执行。
2.我们再来建立一个生产者的类:
package com.mec.about_procuder_customer.core; //生产者
public class Procuder extends ProcuderCustomer implements Runnable { //存放数据的空间
private int[] dataSpace; public Procuder(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
int i = 0; while (true) {
synchronized (lock) {
//判断是否空间已满
if (count < dataSpace.length) {
//产生者放数据
dataSpace[count] = i++;
System.out.println("[" + Thread.currentThread().getName()
+ "]线程生产了一个数:" + dataSpace[count++]
+ " " + count);
try {
//只是为了看的清楚,沉睡2秒
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒消费者
lock.notify();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
3.建立消费者的类:
package com.mec.about_procuder_customer.core; //消费者
public class Customer extends ProcuderCustomer implements Runnable {
//存放数据的空间
private int[] dataSpace; public Customer(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
while (true) {
//加锁
synchronized (lock) {
//判断是否有数据
if (count > 0) {
System.out.println("[" + Thread.currentThread().getName()
+ "]线程消费了一个数:" + dataSpace[--count]);
//唤醒生产者
lock.notifyAll();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
} }
4.测试类:
package com.mec.about_procuder_customer.test; import com.mec.about_procuder_customer.core.Customer;
import com.mec.about_procuder_customer.core.Procuder; public class Test { public static void main(String[] args) {
int[] data = new int[10];
new Procuder(data, "生产者1");
new Procuder(data, "生产者2");
new Customer(data, "消费者");
} }
运行结果: