ReentrantLock 支持多条件变量,用于唤醒指定的部分线程。
/**
* ReentrantLock 方法,用以获取一个条件变量实例,可以理解为不满足条件的线程的暂时等待的区域。
* Returns a {@link Condition} instance for use with this
* {@link Lock} instance.
*/
public Condition newCondition() {
return sync.newCondition();
}
以下为一个条件变量使用的例子:
private static ReentrantLock lock = new ReentrantLock();
//条件
private static boolean hasSmoke = false;
private static boolean hasSnacks = false;
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 0, TimeUnit.MINUTES, new LinkedBlockingDeque<>());
//烟
Condition smoke = lock.newCondition();
//零食
Condition snacks = lock.newCondition();
threadPoolExecutor.submit(() -> {
lock.lock();
try {
//while 防止虚假唤醒
//即没有满足该条件,执行了之后的代码,暂时这么理解
while (!hasSmoke) {
try {
log.info(Thread.currentThread().getName() + " 没有烟,不能干...");
//Condition 对象调用await()方法,放弃持有的锁,进入休息区等待
smoke.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.info("来烟啦,崩一根...");
} finally {
lock.unlock();
}
});
threadPoolExecutor.submit(() -> {
lock.lock();
try {
while (!hasSnacks) {
try {
log.info(Thread.currentThread().getName() + " 零食也不让吃,不能干...");
snacks.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.info("吃饱了,干活...");
} finally {
lock.unlock();
}
});
threadPoolExecutor.submit(() -> {
lock.lock();
try {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
hasSmoke = true;
log.info("送烟的来咯...");
//调用signalAll()方法,唤醒smoke等待区的所有线程
smoke.signalAll();
//唤醒等待区的某一个线程
//smoke.signal();
hasSnacks = true;
log.info("零食来咯...");
snacks.signalAll();
} finally {
lock.unlock();
}
});
threadPoolExecutor.shutdown();
}