Java Condition条件对象

Condition用于管理已经获得了一个锁但是却不能做有用工作的线程。由Lock对象的newCondition()方法一个与当前Lock对象相关联的条件对象,共同管理该锁相关的对象和线程。

当线程已经获得锁,但是因为条件限制,无法继续工作的时候,调用Condition.await()方法,此线程进入该条件对象的等待集。当锁可用时,该线程不能马上解除阻塞。相反,它处于阻塞状态,直到另个线程调用同一条件上的signalAll方法时为止,这个方法可以激活所有等待的线程。Condition还有一个Signal方法,该方法是随机激活一个线程。

SignalAll不会立即激活一个等待线程,它仅仅解除等待线程的阻塞,以便这些线程可以在当前线程退出同步方法之后,通过竞争实现对对象的访问。

/**
 * Created by LvJianwei on 2018/2/11.
 */

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

/**
 * @program: ConditionDemo
 * @description:
 * @author: LvJianwei
 * @create: 2018-02-11 15:57
 **/
public class ConditionDemo {

    public static void main(String[] args) {
        ConditionDemo demo = new ConditionDemo();
        Runnable rAdd = () -> {
            while (true) {
                try {
                    demo.countAdd();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable rReduce = () -> {
            while (true) {
                try {
                    demo.countReduce();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(rReduce);
            t.start();
        }
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(rAdd);
            t.start();
        }


    }

    private Random random=new Random(System.currentTimeMillis());
    private ReentrantLock locker = new ReentrantLock();
    private Condition enough;
    private int count = 0;
    private int enoughCount=3;

    public ConditionDemo() {
        enough = locker.newCondition();
    }

    public void caculateWithLock() {
        locker.lock();
        try {
            int randomResult=random.nextInt();
            boolean shouldWait=randomResult%5==0;
            System.out.printf("randomResult:%d%%5==0:%b,%s
",randomResult,shouldWait,shouldWait?"await":"continue");
            while(!shouldWait)
            {
                countAdd();
                enough.await();
            }
            countReduce();
            printLockStatus();
            longTimeLock();
            System.out.println("final count:" + count);
            enough.signalAll();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            locker.unlock();
        }
    }

    public void countAdd() {
        locker.lock();
        try {
            count++;
            System.out.printf("Add,count:%d
", count);
            if(count>enoughCount){
                System.out.println("signAll");
                enough.signalAll();
            }
        }
        finally {
            locker.unlock();
        }
    }

    public void countReduce() {
        System.out.println("countReduce start,threadID:"+Thread.currentThread().getId());
        locker.lock();
        try {
            while (count<enoughCount){
                System.out.printf("threadID:%s,await,count:%d
",Thread.currentThread().getId(),count);
                enough.await();
            }
            count--;
            System.out.printf("threadID:%s,reduce,count:%d
",Thread.currentThread().getId(),count);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            locker.unlock();
        }
    }

    public void longTimeLock() {
        locker.lock();
        try {
            printLockStatus();
            int locktime = 3000;
            System.out.printf("longTimeLock:%d ms
", locktime);
            Thread.sleep(locktime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            locker.unlock();
        }
    }

    private void printLockStatus() {
        System.out.printf("lock count:%d,queueLength:%d
", locker.getHoldCount(), locker.getQueueLength());
    }
}

add和reduce方法分别关联5个线程,对于reduce方法,只有当count>=enoughCount时才会进行减操作,否则就等待,由add方法,当count>enoughCount时,触发signalall方法。

下面运行结果可以看出,开始的13、11、12线程启动后,发现count<enoughCount,进入阻塞状态,直到add方法增加count到大于enoughCount时才执行减操作。

countReduce start,threadID:13
threadID:13,await,count:0
countReduce start,threadID:11
threadID:11,await,count:0
Add,count:1
Add,count:2
countReduce start,threadID:12
threadID:12,await,count:2
Add,count:3
Add,count:4
signAll
countReduce start,threadID:15
threadID:15,reduce,count:3
countReduce start,threadID:14
threadID:14,reduce,count:2
原文地址:https://www.cnblogs.com/lvjianwei/p/8442765.html