消费者生产者应该包括以下部分:
1被消费和生产的对象(car)
2生产者(Producer)
3消费者(Consumer)
4客户端调用
被操作类
public class Car {
private boolean waxStatus = false;//车的上蜡状态
private Lock lock = new ReentrantLock();
Condition conditionC = lock.newCondition();//消费者的condition
Condition conditionP = lock.newCondition();//生产者的condition
// 生产者生产
public void waxed() {
lock.lock();//为什么此处上锁,1保证操作原子性,2实现线程间通讯需要调用signalAll,signalAll的使用需要在同步代码块中
try{
waxStatus = true;
System.out.println("on");
conditionC.signal();//生产完叫醒消费者
}finally{
lock.unlock();
}
}
// 生产者生产后等待
public void waitForBuffered() throws InterruptedException{
lock.lock();
try{
// 这里while循环,是因为Producer中的while,即一直生产,产品消费前生产者一直等待
while(waxStatus == true){//打蜡线程,打蜡之后调用,所以此处判断是已经打蜡的时候应该wait
conditionP.await();//生产者生产完进入等待
}
}finally{
lock.unlock();
}
}
//消费者消费
public void buffered() {
lock.lock();
try{
waxStatus = false;
System.out.println("off");
conditionP.signal();//消耗完叫醒生产者
}finally{
lock.unlock();
}
}
//消费者消费后等待
public void waitforWaxed() throws InterruptedException{
lock.lock();
try{
while(waxStatus == false){
conditionC.await();//消费者者消费完进入等待
}
}finally{
lock.unlock();
}
}
}
生产者
public class Producer implements Runnable {
Car car;
public Producer(Car car) {
this.car = car;
}
@Override
public void run() {
try {
while (true) {// ?????
// while (!Thread.interrupted()) {// 持续的生产,不是仅仅生产一个
car.waxed();
car.waitForBuffered();//打蜡线程,打蜡之后调用,所以此处判断是已经打蜡的时候应该wait
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
消费者:
public class Consumer implements Runnable {
Car car;
public Consumer(Car car) {
this.car = car;
}
@Override
public void run() {
try {
while(!Thread.interrupted()){
car.waitforWaxed();
car.buffered();
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
客户端
public class Client {
public static void main(String[] args) {
Car car = new Car();
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Producer(car));
executor.execute(new Consumer(car));
try {
TimeUnit.MILLISECONDS.sleep(1207);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdownNow();
}
}
1 为哈有且仅有一个lock?
因为要求线程安全,所以使用这个lock就是锁资源,所有的线程都必须拿到这个锁才能干活;
2 object.wait和condition.await的区别
使用上,wait必须用在synchronized中,await必须用在lock.lock()中
叫醒方式不同,wait对应notify,await对应signal
condition能实现更细粒度的线程调度
3 为甚需要两个condition?一个condition是否可以
Condition的强大之处在于它可以为多个线程间建立不同的Condition, 使用synchronized/wait()只有一个阻塞队列,notifyAll会唤起所有阻塞队列下的线程,而使用lock/condition,可以实现多个阻塞队列,signalAll只会唤起某个阻塞队列下的阻塞线程。
上面就位生产者和消费者线程组建立了两个阻塞对列conditionC和conditionP,这样conditionC调用await只会叫醒消费者的线程。
一个condition也是可以的,但是这个时候效率会有所下降,和synchronized、wait方式一样了,没有发挥
4 为啥强制wait必须用在synchronized中?否则IllegalMonitorStateException
(1)为什么wait()必须在同步(Synchronized)方法/代码块中调用?
答:调用wait()就是释放锁,释放锁的前提是必须要先获得锁,先获得锁才能释放锁。
(2)为什么notify(),notifyAll()必须在同步(Synchronized)方法/代码块中调用?
答:notify(),notifyAll()是将锁交给含有wait()方法的线程,让其继续执行下去,如果自身没有锁,怎么叫把锁交给其他线程呢;
————————————————
原文链接:https://blog.csdn.net/qq_42145871/article/details/81950949
还有一种实现生产者消费者方式是通过BlockingQueue,主要代码如下:
BlockingQueue<LiftOff> queue = new LinkedBlockingQueue();
while(!Thread.isInturrped()){
LiftOff off = queue.take();//注意如果此时队列为空,那队列将挂起任务,但当有更多的元素可用时,将恢复任务,十分灵活,代替了wait和notify的握手方式
off.run();
}