您的位置:首页 > 编程语言 > Java开发

利用ReentrantLock的Condition实现线程之间的通信

2015-12-30 17:17 519 查看
Condition可以实现线程之间的通信,通过awat和signal两个方法来实现线程之间的通信协作。

现在我们利用Condition来实现一个功能:开启3个线程,让线程按顺序循环打印 A、B、C。

主代码如下:

static final ReentrantLock lock = new ReentrantLock();
static AtomicBoolean firstA = new AtomicBoolean(true);
static class PrintRunable implements Runnable{

private String str;
private Condition await;
private Condition signal;

public PrintRunable(String str, Condition await, Condition signal) {
this.str = str;
this.await = await;
this.signal = signal;
}

@Override
public void run() {
//第一次要打印A时,是没有任何人通知的
if (firstA.get() && "A".equals(str)) {
lock.lock();
try {
System.out.println(str);
firstA.getAndSet(true);
TimeUnit.SECONDS.sleep(1);
signal.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
while (true) {
while (true) {
lock.lock();
try {
//等待被通知
await.await();
System.out.println(str);
TimeUnit.SECONDS.sleep(1);
//通知被等待的下一个线程
signal.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}测试:
@Test
public void reentrantLockTest() throws Exception {
final Condition condition1 = lock.newCondition();
final Condition condition2 = lock.newCondition();
final Condition condition3 = lock.newCondition();

Thread a = new Thread(new PrintRunable("A",condition1,condition2));
Thread b = new Thread(new PrintRunable("B",condition2,condition3));
Thread c = new Thread(new PrintRunable("C",condition3,condition1));

b.start();
c.start();
a.start();
b.join();
a.join();
c.join();

}

控制台打印:
A
B
C
A
B
C
A
B
C
总结:
ReentrantLock 是独占锁,一个线程拿到锁后如果不释放,那么另外一个线程肯定是拿不到锁,所以在 lock.lock() 和 lock.unlock() 之间可能有一次释放锁的操作(同样也必然还有一次获取锁的操作)。不管take() 还是 put() ,在进入 lock.lock() 后唯一可能释放锁的操作就是 await()了。也就是说 await() 操作实际上就是释放锁,然后挂起线程,一旦条件满足就被唤醒,再次获取锁!这个有点像wait和notify了,wait也会释放锁,sleep是不会释放锁的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 java多线程