下面是一段用synchronized同步关键字实现的线程轮流对count+1的代码
两个线程轮流打印
// 两个线程轮流给cont加1,直到count=10
public static void synchronizedPrint(Object lock) {
Runnable runnable = () -> {
synchronized (lock) {
while (count <= 10) {
System.out.println(Thread.currentThread().getName() + " count = " + count++);
try {
lock.notify();
lock.wait();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//这里是保证当count==10的时候,处于wait的线程可以被释放掉
lock.notify();
}
};
new Thread(runnable).start();
new Thread(runnable).start();
}
这段代码如果让你用ReentrantLock来实现,你会怎么做?如果你只用lock()和unlock()方法,是不是很头疼?我们先看实现。
public static void lockPrint() {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Runnable runnable = () -> {
lock.lock();
try {
while (count <= 10) {
System.out.println(Thread.currentThread().getName() + " count = " + count++);
condition.signal();
condition.await();
}
condition.signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
};
new Thread(runnable).start();
new Thread(runnable).start();
}
我们可以看到,其实代码主流程没有变,只是引入了Condition去做原本objecet中wait()和notify()的操作。下面介绍一下Condition的方法
ConditionObject
ConditionObject 是ReentrantLock内部对Condition接口的实现
- await():使当前线程等待,直到被通知或中断。调用此方法后,当前线程会被阻塞,并释放锁。
- awaitUninterruptibly():使当前线程等待,直到被通知,但不响应中断。
- awaitNanos(long nanosTimeout):使当前线程等待指定的时间,直到被通知、中断或超时。
- awaitUntil(Date deadline):使当前线程等待,直到被通知、中断或到达指定的截止时间。
- signal():唤醒一个等待的线程。如果有多个线程在等待,则随机选择一个线程唤醒。
- signalAll():唤醒所有等待的线程。
可以看到,如果ReentrantLock只有lock()和unlock(),是很难做到线程间的通信的,引入了ConditionObject以后,我们就可以更加灵活的操作线程