场景描述:开发人员经常会遇到这样的方法调用场景:调用一个方法时等待一段时间(一般来说是给定一个时间段),如果该方法能够在给定的时间段之内得到结果, 那么将结果立刻返回, 反之,超时返回默认结果。
·等待持续时间: REMAINING=T。
·超时时间: FUTURE=now+T。
这时仅需要wait(REMAINING)即可, 在wait(REMAINING)返回之后会将执行:
REMAINING=FUTURE–now。 如果REMAINING小于等于0, 表示已经超时, 直接退出, 否则将
继续执行wait(REMAINING)。
一个简单的数据库连接池(只是简单展示一下这个模式,就不写怎么用了)
public class ConnectionPool { //Connection只是一个接口,具体实现是由数据库厂商决定的 private LinkedList<Connection> pool = new LinkedList<Connection>() ; public ConnectionPool(int initialSize) { if (initialSize > 0) { for (int i = 0; i < initialSize; i++) { pool. addLast(ConnectionDriver. createConnection()) ; } } } public void releaseConnection(Connection connection) { if (connection ! = null) { synchronized (pool) { // 连接释放后需要进行通知, 这样其他消费者能够感知到连接池中已经归还了一个连接 pool.addLast(connection) ; pool.notifyAll() ; } } } // 在mills内无法获取到连接, 将会返回null public Connection fetchConnection(long mills) throws InterruptedException { synchronized (pool) { // 完全超时 if (mills <= 0) { while (pool. isEmpty() ) { pool.wait() ; } return pool. removeFirst() ; } else { long future = System.currentTimeMillis() + mills; long remaining = mills; while (pool.isEmpty() && remaining > 0) { //注意这里两个条件必须同时满足 pool.wait(remaining) ; remaining = future - System.currentTimeMillis() ; } Connection result = null; if (! pool.isEmpty() ) { result = pool.removeFirst() ; } return result; } } } }
在这一段代码中
while (pool.isEmpty() && remaining > 0) {
pool.wait(remaining) ;remaining = future - System.currentTimeMillis() ;
}
这里的wait()方法我是这么理解的,在wait方法执行后,一直经过了remaining毫秒后还未有其他线程唤醒他时,这个线程相当于自己唤醒了,但是这个自己唤醒自己还是有一个条件,就是他必须获取pool的锁,否则就算超时时间到了他还是被阻塞的,不能继续往下执行,所以这个线程最终的超时时间不一定是刚好的remaining毫秒。当然这里加个超时时间还是有用的,毕竟不会永远阻塞自己