1. 程式人生 > >使用Condition實現生產者消費者

使用Condition實現生產者消費者

使用Condtion實現生產者消費者可以精確控制喚醒生產者還是消費者執行緒

與synchronized的等待喚醒機制相比Condition具有更多的靈活性以及精確性,這是因為notify()在喚醒執行緒時是隨機(同一個鎖),而Condition則可通過多個Condition例項物件建立更加精細的執行緒控制,也就帶來了更多靈活性了,我們可以簡單理解為以下兩點

  • 通過Condition能夠精細的控制多執行緒的休眠與喚醒。

  • 對於一個鎖,我們可以為多個執行緒間建立不同的Condition。

程式碼實現:

1、Condition提供了await()方法將當前執行緒阻塞,並提供signal()方法支援另外一個執行緒將已經阻塞的執行緒喚醒。
2、Condition需要結合Lock使用
3、執行緒呼叫await()方法前必須獲取鎖,呼叫await()方法時,將執行緒構造成節點加入等待佇列,同時釋放鎖,並掛起當前執行緒
4、其他執行緒呼叫signal()方法前也必須獲取鎖,當執行signal()方法時將等待佇列的節點移入到同步佇列,當執行緒退出臨界區釋放鎖的時候(ReentrantLock.unlock),喚醒同步佇列的首個節點

資源:

package com.huige.review;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author liuhui
 * @description
 * @create 2018/10/18 上午11:22
 */
public class ResourceCondtion {
    private Lock lock = new ReentrantLock();
    private Condition consumeCondition = lock.newCondition();
    private Condition productCondition = lock.newCondition();
    private int number = 0;

    public  void increace(){
        lock.lock();
        try {
            while(number > 0){
                productCondition.await();
            }
            number ++;
            System.out.println("生產後"+Thread.currentThread().getName()+" : "+number);
            consumeCondition.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void decreace(){
        lock.lock();
        try {
            while(number == 0){
                consumeCondition.await();
            }
            number --;
            System.out.println("消費後"+Thread.currentThread().getName()+" : "+number);
            productCondition.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

    public static void main(String[] args) {
        ResourceCondtion resource = new ResourceCondtion();
        new Thread(new ProductCondition(resource)).start();
        new Thread(new ProductCondition(resource)).start();
        new Thread(new ConsumeCondition(resource)).start();
        new Thread(new ConsumeCondition(resource)).start();
        new Thread(new ConsumeCondition(resource)).start();
    }
}

生產者:

package com.huige.review;

/**
 * @author liuhui
 * @description
 * @create 2018/10/18 下午1:51
 */
public class ProductCondition implements Runnable {
    private  ResourceCondtion resource ;
    public ProductCondition(ResourceCondtion resource){
        this.resource = resource;
    }
    @Override
    public void run() {
        for (int i = 0;i<10;i++) {
            try {
                Thread.sleep(100);
            }catch (Exception e){

            }
            resource.increace();
        }
    }
}

消費者:

package com.huige.review;

/**
 * @author liuhui
 * @description
 * @create 2018/10/18 下午1:54
 */
public class ConsumeCondition implements Runnable{
    private  ResourceCondtion resource ;
    public ConsumeCondition(ResourceCondtion resource){
        this.resource = resource;
    }
    @Override
    public void run() {
        for (int i = 0;i<10;i++) {
            try {
                Thread.sleep(150);
            }catch (Exception e){

            }
            resource.decreace();
        }
    }
}