生产者消费者模型:
有一个容器来盛放商品,左边有生产者生产该商品,并将生产的商品放入该容器中;右边有消费者,从容器中拿走商品;
容器中商品的个数不可能为负数;当容器中没有商品时,消费者无法消费;当容器中满的时候,生产者不能再生产商品了;
下面来实现该现象:
(1)使用synchronized的方式
/*
* 生产者消费者模型
* synchronized、wait/notify的方式
* */
public class Main {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
data.product();
}
}, "生产者").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
data.consumer();
}
}, "消费者").start();
}
}
class Data {
private Integer num = 0;
/*生产者*/
public synchronized void product() {
/*判断的时候,必须使用while循环,而不能使用if,因为使用if会存在线程虚假唤醒的问题,虚假唤醒是指wait
* 方法会在除了notify以外的情况被唤醒,而此时是不应该被唤醒的,使用while可以多次检测,避免虚假唤醒的问题*/
/*停止生产的条件*/
/* while (num!=0){*/
while (num >= 20) {//如果num的超过某个值,即容器满了之后,则阻塞,不让他再生产了
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
this.notify();//唤醒consumer
System.out.println(Thread.currentThread().getName() + "--" + num);
}
/*消费者*/
public synchronized void consumer() {
while (num == 0) {//如果num==0,则阻塞,不让他再减了
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
this.notify();//唤醒product
System.out.println(Thread.currentThread().getName() + "--" + num);
}
}
(2)使用Lock的方式
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* 生产者、消费者
* Lock的方式
* Lock的Condition接口也提供了类似Object的监视方法,与Lock配合可以实现等待/通知模式,Condition对象依赖于Lock对象的
*
* */
public class Main2 {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
data.product();
}
}, "生产者").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
data.consumer();
}
}, "消费者").start();
}
}
class Data2{
private Integer num=0;
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
/*生产者*/
public void product(){
try {
lock.lock();//加锁
while (num >= 20) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
condition.signal();//唤醒consumer
System.out.println(Thread.currentThread().getName() + "--" + num);
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();//释放锁
}
}
/*消费者*/
public void consumer(){
try {
lock.lock();//加锁
while (num == 0) {//如果num==0,则阻塞,不让他再减了
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
condition.signal();//唤醒product
System.out.println(Thread.currentThread().getName() + "--" + num);
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();//释放锁
}
}
}