public Ticket lock(String resourceName, long duration, long wait) { long maxWait = System.currentTimeMillis() + wait; while (System.currentTimeMillis() < maxWait) { Ticket t = null; synchronized (this) { t = (Ticket) locks.get(resourceName); if (t == null) { t = new SimpleTicket(resourceName, duration); locks.put(resourceName, t); return t; } else if (t.isExpired()) { t.cancel(); continue; } } synchronized (t) { try { t.wait(Math.min(1000, wait)); } catch (InterruptedException e) { } } } return null; }