Condition条件对象 主要是用于线程间通信,当满足某个条件时发生,发生后又可以唤醒其他等待该条件中的线程
Condition的使用代码示例
public class ConditionTest
{
public static void main(String[] args) throws InterruptedException
{
final Output output = new Output();
new Thread(new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
for(int i = 0; i < 20; i++)
{
try
{
output.sub(i);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
for(int i = 0; i < 20; i++)
{
output.main(i);
}
}
}
class Output
{
//lock
private Lock lock = new ReentrantLock();
//Condition必须是结合lock一起使用
private Condition condition = lock.newCondition();
//判断条件
public static boolean isMain = true;
public void main(int loop) throws InterruptedException
{
lock.lock();
try
{
while(!isMain)
{
//注意await() 不是wait()
condition.await();
}
for(int i = 0; i < 50; i++)
{
System.out.println("[Main:]" + Thread.currentThread().getName()
+ " i = " + i + " #loop = " + loop);
}
isMain = false;
//通知等待中的线程 注意 是 signal() 不是notify()
condition.signal();
}
finally
{
lock.unlock();
}
}
public void sub(int loop) throws InterruptedException
{
lock.lock();
try
{
while(isMain)
{
//注意await() 不是wait()
condition.await();
}
for(int i = 0; i < 20; i++)
{
System.out.println("[Sub:]" + Thread.currentThread().getName()
+ " i = " + i + " #loop = " + loop);
}
isMain = true;
//通知等待中的线程 注意 是 signal() 不是notify()
condition.signal();
}
finally
{
lock.unlock();
}
}
}
能够创建多个Condition的实例,可以唤醒指定条件的线程,使线程间的通信更加的高效。不过要注意的是 等待使用的是await()而不是wait(),唤醒使用的是signal()而不是notify()
JDK中的示例 一个固定大小的缓冲区的实现
class BoundedBuffer
{
final Lock lock = new ReentrantLock();
/**
* 两个Condition
* notFull 缓冲区是否已满
* notEmpty 缓冲区是否为空
*/
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
//定义可以存放100个对象的缓冲区
final Object[] items = new Object[100];
//存放对象的地址 取对象的地址 表示当前缓冲区里存放对象的数量
int putptr, takeptr, count;
/**
* 存入对象
* @param x
* @throws InterruptedException
*/
public void put(Object x) throws InterruptedException
{
lock.lock();
try
{
//判断当前缓冲区中存放的对象数量是否与缓冲区的最大容量相等
while (count == items.length)
{
//如果相等,则让当前存放数据的线程处于等待状态
notFull.await();
}
//如果不相等,则将对象存入缓冲区
items[putptr] = x;
//判断存放对象的地址是否已经超出缓冲区数组的大小
if (++putptr == items.length)
{
//如果超出,则从第一个地址开始
putptr = 0;
}
//将缓冲区对象数据数量 +1
++count;
//notEmpty条件满足,通知等待中的线程继续运行
notEmpty.signal();
}
finally
{
lock.unlock();
}
}
/**
* 取出对象
* @return
* @throws InterruptedException
*/
public Object take() throws InterruptedException
{
lock.lock();
try
{
//判断当前缓冲区中是否存在对象数据
while (count == 0)
{
//不存在数据 则进入等待状态
notEmpty.await();
}
//根据取数据的地址 从缓冲区中取出对象数据
Object x = items[takeptr];
//判断获取对象的地址是否已经超出缓冲区数组的大小
if (++takeptr == items.length)
{
//如果超出,则从第一个地址开始
takeptr = 0;
}
//将缓冲区对象数据数量 -1
--count;
//notFull条件满足,通知等待中的线程继续运行
notFull.signal();
return x;
}
finally
{
lock.unlock();
}
}
}