文章目录
一、生产者和消费者实现
Clothes.java:
package com.xiaoqiang.interview.thread;
/**
* Created by Huiq on 2021/4/22.
*/
public class Clothes {
private String name;
private String sex;
public synchronized void set(String name, String sex) {
this.name = name;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.sex = sex;
System.out.println("生产:" + getSex() + "-" + getName());
}
public synchronized void get() {
System.out.println("消费:" + getSex() + "-" + getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
ProducerConsumerDemo.java:
package com.xiaoqiang.interview.thread;
/**
* Created by Huiq on 2021/4/22.
*/
public class ProducerConsumerDemo {
public static void main(String[] args) {
Clothes person = new Clothes();
new Thread(new Producer(person)).start();
new Thread(new Consumer(person)).start();
}
}
class Producer implements Runnable {
private Clothes person;
public Producer(Clothes person) {
this.person = person;
}
@Override
public void run() {
for (int i=0; i<50; i++) {
if (i % 2 == 0) {
this.person.set("背心", "男");
} else {
this.person.set("连衣裙", "女");
}
}
}
}
class Consumer implements Runnable {
private Clothes person;
public Consumer(Clothes person) {
this.person = person;
}
@Override
public void run() {
for (int i=0; i<50; i++) {
this.person.get();
}
}
}
运行之后并不满足我们的要求,修改成生产后再消费,消费完再生产:
package com.xiaoqiang.interview.thread;
public class Clothes {
private String name;
private String sex;
private boolean isEmpty = true;
public synchronized void set(String name, String sex) {
if (!isEmpty) { // 不为空,生产者应该停下来,等到消费者去消费
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.sex = sex;
System.out.println("生产:" + getSex() + "-" + getName());
isEmpty = false;
this.notifyAll(); // 不为空的时候唤醒消费者,起来消费
}
public synchronized void get() {
if (isEmpty) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费:" + getSex() + "-" + getName());
isEmpty = true;
this.notifyAll(); // 唤醒生产者该生产了
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
考察点:wait
和notifyall
的使用,一定要在synchronized的里面使用
二、可重入锁实现
修改Clothes.java为:
package com.xiaoqiang.interview.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Clothes {
private String name;
private String sex;
private boolean isEmpty = true;
private ReentrantLock lock = new ReentrantLock(); // 创建可重入锁对象
private Condition condition = lock.newCondition();
// 生产者
public synchronized void set(String name, String sex) {
lock.lock();
if (!isEmpty) { // 不为空,生产者应该停下来,等到消费者去消费
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
try {
Thread.sleep(500);
this.sex = sex;
System.out.println("生产:" + getSex() + "-" + getName());
isEmpty = false;
condition.signal(); // 不为空的时候唤醒消费者,起来消费
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 把锁解除掉
}
}
// 消费者
public void get() {
lock.lock();
if (isEmpty) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
System.out.println("消费:" + getSex() + "-" + getName());
isEmpty = true;
condition.signal(); // 唤醒生产者该生产了
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}