简介
生产者消费者是线程并发的经典案例, 保证线程安全且更好的协作。 线程安全是避免多线程操作同一个数据造成的脏读, 更好的协作是多个线程的状态切换可控且有目的性。 类比现实中的问题有点像交通警指挥交通。
单生产单消费
生产者
public class Product {
private String lock;
public Product(String lock) {
super();
this.lock = lock;
}
public void setValue(){
try {
synchronized (lock) {
if(!StringObject.value.equals("")){
//有值,不生产
lock.wait();
}
String value = System.currentTimeMillis()+""+System.nanoTime();
System.out.println("set的值是:"+value);
StringObject.value = value;
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
消费者
public class Consumer {
private String lock;
public Consumer(String lock) {
super();
this.lock = lock;
}
public void getValue(){
try {
synchronized (lock) {
if(StringObject.value.equals("")){
//没值,不进行消费
lock.wait();
}
System.out.println("get的值是:"+StringObject.value);
StringObject.value = "";
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
生产者线程
public class ThreadProduct extends Thread{
private Product product;
public ThreadProduct(Product product) {
super();
this.product = product;
}
@Override
public void run() {
//死循环,不断的生产
while(true){
product.setValue();
}
}
}
消费者线程
public class ThreadConsumer extends Thread{
private Consumer consumer;
public ThreadConsumer(Consumer consumer) {
super();
this.consumer = consumer;
}
@Override
public void run() {
//死循环,不断的消费
while(true){
consumer.getValue();
}
}
}
开启生产者/消费者模式
public class Test {
public static void main(String[] args) throws InterruptedException {
String lock = new String("");
Product product = new Product(lock);
Consumer consumer = new Consumer(lock);
ThreadProduct pThread = new ThreadProduct(product);
ThreadConsumer cThread = new ThreadConsumer(consumer);
pThread.start();
cThread.start();
}
}
打印
set的值是:148827033184127168687409691
get的值是:148827033184127168687409691
set的值是:148827033184127168687449887
get的值是:148827033184127168687449887
set的值是:148827033184127168687475117
get的值是:148827033184127168687475117
多生产多消费
生产者
public class Product {
private ReentrantLock lock;
private Condition condition;
public Product(ReentrantLock lock, Condition condition) {
super();
this.lock = lock;
this.condition = condition;
}
public void setValue() {
try {
lock.lock();
while (!StringObject.value.equals("")) {
// 有值,不生产
condition.await();
}
String value = System.currentTimeMillis() + "" + System.nanoTime();
System.out.println("set的值是:" + value);
StringObject.value = value;
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
消费者
public class Consumer {
private ReentrantLock lock;
private Condition condition;
public Consumer(ReentrantLock lock,Condition condition) {
super();
this.lock = lock;
this.condition = condition;
}
public void getValue(){
try {
lock.lock();
while(StringObject.value.equals("")){
//没值,不进行消费
condition.await();
}
System.out.println("get的值是:"+StringObject.value);
StringObject.value = "";
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
开启多生产/多消费模式
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Condition newCondition = lock.newCondition();
Product product = new Product(lock,newCondition);
Consumer consumer = new Consumer(lock,newCondition);
for(int i=0;i<3;i++){
ThreadProduct pThread = new ThreadProduct(product);
ThreadConsumer cThread = new ThreadConsumer(consumer);
pThread.start();
cThread.start();
}
}
输出结果:
set的值是:148827212374628960540784817
get的值是:148827212374628960540784817
set的值是:148827212374628960540810047
get的值是:148827212374628960540810047
注意
-
单一生产消费的判断用的是if, 多生产消费用的是while, 因为被唤醒的线程不知道它的同类线程是否已经把活儿干完了, 所以还要再次进行判断。
-
notify 换成了 notifyall, 避免一个线程把活干完之后又唤起了同类线程, 这样就会进入到假死状态。