admin管理员组

文章数量:1599529

消费者生产者应该包括以下部分:

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/qq_42145871/article/details/81950949

还有一种实现生产者消费者方式是通过BlockingQueue,主要代码如下:

BlockingQueue<LiftOff> queue = new LinkedBlockingQueue();
while(!Thread.isInturrped()){
   LiftOff off = queue.take();//注意如果此时队列为空,那队列将挂起任务,但当有更多的元素可用时,将恢复任务,十分灵活,代替了wait和notify的握手方式
   off.run();
}

 

本文标签: 用在实例区别Lockcondition