我已经为https://www.programcreek.com/2014/08/leetcode-design-phone-directory-java/实现了一个解决方案,如下面的清单1所示:
class PhoneDirectory {
private final LinkedList<Integer> q;
private final boolean[] used;
public PhoneDirectory(int maxNumbers) {
q = new LinkedList<>();
used = new boolean[maxNumbers];
for (int i = 0; i < maxNumbers; i++) {
q.offer(i);
}
}
public int get() {
if (!q.isEmpty()) {
int num = q.poll();
used[num] = true;
return num;
}
return -1;
}
public void release(int number) {
if (used[number]) {
used[number] = false;
q.offer(number);
}
}
}
但是,以上解决方案是单线程的,如果多个线程同时访问PhoneDirectory对象,它将失败。
因此,我在下面的清单2中实现了线程安全版本,其逻辑略有不同:
public class PhoneDirectory {
private int curr;
private final int[] next;
private final Object lock = new Object();
private final long SLEEP = 2000;
public PhoneDirectory(int size) {
next = new int[size];
curr = 0;
for (int i = 0; i < size; i++) {
next[i] = (i + 1) % size;
}
}
public int get(final long sleepInSeconds) throws InterruptedException {
synchronized (lock) {
final long sleepInMills = sleepInSeconds * 1000;
long startTime = System.currentTimeMillis();
try {
while (next[curr] == -1) {
if (System.currentTimeMillis() - startTime >= sleepInMills) {
return -1;
}
lock.wait(SLEEP);
}
int res = curr;
curr = next[curr];
next[res] = -1;
return res;
} finally {
lock.notify();
}
}
}
public void release(int number) {
synchronized (lock) {
try {
if (next[number] != -1) {
return;
}
next[number] = curr;
curr = number;
} finally {
lock.notify();
}
}
}
}
免责声明:我不是在看代码的内部机制,而只是在线程方面。