上一篇[Java多线程之并发协作生产者消费者设计模式]已经讲述了在Java的多线程中,如何处理并发安全的生产者消费者设计模式,不了解的可以先看看上一篇的内容
上一篇中的效率和优化问题
- 在上一篇中生产者消费者设计模式中最后为了不产生类似于“死锁”,就是多线程全部wait()导致程序无法向下继续运行的情况,我们采用了notifyAll()这个方法,那么有什么问题呢?
- 效率问题,notifyAll()方法是将在执行了wait()方法后的所有等待线程都唤醒了,那么也就是说,即唤醒了生产者线程也唤醒了消费者线程
- 优化方案:我们没有必要把大家都唤醒,只需要让生产者线程唤醒消费者线程,消费者线程唤醒生产者线程即可。
jdk1.5的对多线程并发安全的新解决方案
- jdk1.5以后将同步和锁封装成了对象。并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作。
- Lock接口: 出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。同时更为灵活。可以一个锁上加上多组监视器。
- lock():获取锁。
- unlock():释放锁,通常需要定义finally代码块中。
- Condition接口:出现替代了Object中的wait notify notifyAll方法。将这些监视器方法单独进行了封装,变成Condition监视器对象。可以任意锁进行组合。
- await();线程等待—>等同于wait();【监视器的方法】
- signal();唤醒线程——>等同于notify();【监视器的方法】
- signalAll();唤醒全部等待中的线程——>等同于notifyAll();【监视器的方法】
最终经过优化的代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by yuandl on 2016-10-12.
* 要生产的资源
*/
public class Resource {
private int number = 0;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_consumer = lock.newCondition();
private Condition condition_producer = lock.newCondition();
public void create() {
lock.lock();
try {
while (flag) {
condition_producer.await();
}
number++;
System.out.println("生产者--------------" + number);
flag = true;
condition_consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void destroy() {
lock.lock();
try {
while (!flag) {
condition_consumer.await();
}
System.out.println("消费者***" + number);
flag = false;
condition_producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* Created by yuandl on 2016-10-12.
* 生产者
*/
public class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.create();
}
}
}
/**
* Created by yuandl on 2016-10-12.
* 消费者
*/
public class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.destroy();
}
}
}
package thread.produceconsumer2;
/**
* Created by yuandl on 2016-10-12.
*/
public class MainTest {
public static void main(String args[]) {
Resource resource = new Resource();
new Thread(new Producer(resource)).start();
new Thread(new Producer(resource)).start();
new Thread(new Consumer(resource)).start();
new Thread(new Consumer(resource)).start();
}
}
生产者--------------381
消费者***381
生产者--------------382
消费者***382
生产者--------------383
消费者***383
生产者--------------384
消费者***384
生产者--------------385
消费者***385
生产者--------------386
消费者***386
生产者--------------387
消费者***387
生产者--------------388
消费者***388
生产者--------------389
消费者***389
生产者--------------390
消费者***390
生产者--------------391
消费者***391