java并发编程 之 Condition(等待和通知)

时间:2021-11-21 17:59:09

Condition的功能类似在传统线程技术中的Object.wait和Object.notity的功能。一个锁内部可以有多个Condition,即有多路等待和通知,可以参看Jdk1.5提供的Lock和Condition实现的可阻塞队列的应用案例。在传统的线程机制中一个监视器对象上只能有一路等待和通知,要想实现多路等待和通知,必须嵌套使用多个同步监视器对象。
例一:
JDK文档中提供了一个很不错的示例(http://docs.oracle.com/javase/6/docs/api/ ),用Condition实现一个阻塞队列,代码如下:

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



public class BoundedBuffer {

final Lock lock = new ReentrantLock();

final Condition notFull = lock.newCondition();

final Condition notEmpty = lock.newCondition();



final Object[] items = new Object[100];

int putptr, takeptr, count;



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;

++count;

notEmpty.signal();

} finally {

lock.unlock();

}

}



public Object take() throws InterruptedException {

lock.lock();

try {

while (count == 0)

notEmpty.await();

Object x = items[takeptr];

if (++takeptr == items.length)

takeptr = 0;

--count;

notFull.signal();

return x;

} finally {

lock.unlock();

}

}

}

例二:
三个线程 循环打印 : 线程1唤醒线程2,线程2唤醒线程3,线程3唤醒线程1。

package com.huang.test;

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

/**
* java 条件阻塞——condition
* 三个线程 循环打印 : 线程1唤醒线程2,线程2唤醒线程3,线程3唤醒线程1
* @author wuseyukui
*
*/

public class ThreadTest {

private boolean isMainRun = true;
private boolean isSub1Run = false;
private boolean isSub2Run = false;
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();

public static void main(String[] args) {
new ThreadTest().init();
}

private void init() {
new ThreadMain().start();
new ThreadSon1().start();
new ThreadSon2().start();
}

class ThreadMain extends Thread {
@Override
public void run() {
for (int i = 1; i < 6; i++) {
main(i);
}
}

}

class ThreadSon1 extends Thread {
@Override
public void run() {
for (int i = 1; i < 6; i++) {
sub1(i);
}
}
}

class ThreadSon2 extends Thread {
@Override
public void run() {
for (int i = 1; i < 6; i++) {
sub2(i);
}
}
}

private /*synchronized*/ void main(int i) {
lock.lock();
while (!isMainRun) {
try {
// wait();
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 10; j++) {
System.out.println(" 主线程打印:" + (j + 1) + ",第" + i + "个循环");
}

isSub1Run = true;
isMainRun = false;
condition2.signal();
// notify();
lock.unlock();
}

private /*synchronized*/ void sub1(int i) {
lock.lock();
while (!isSub1Run) {
try {
// wait();
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 20; j++) {
System.out.println(" 子线程1打印:" + (j + 1) + ",第" + i + "个循环");
}

isSub2Run = true;
isSub1Run = false;
condition3.signal();
// notify();
lock.unlock();
}

private /*synchronized*/ void sub2(int i) {
lock.lock();
while (!isSub2Run) {
try {
// wait();
condition3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 20; j++) {
System.out.println(" 子线程2打印:" + (j + 1) + ",第" + i + "个循环");
}

isMainRun = true;
isSub2Run = false;
condition1.signal();
// notify();
lock.unlock();
}

}