public class Rooms {
private Lock lock;
private Condition[] conditions;
private int[] waits;
private int[] acquire;
private int[] leave;
private Handler[] handlers;
private final int number;//房间数
private int currRoom;//当前房间标号
public Rooms(int m) {
number = m;
init();
}
private void init() {
lock = new ReentrantLock();
conditions = new Condition[number + 1];
for (int i = 0, len = conditions.length; i < len; ++i) {
conditions[i] = lock.newCondition();
}
waits = new int[number + 1];
acquire = new int[number + 1];
leave = new int[number + 1];
handlers = new Handler[number + 1];
currRoom = -1;
}
private boolean toWait(int index) {
if (currRoom == -1) {
return false;
}
if (currRoom != index) {
return true;
}
for (int i = 1; i <= number; ++i) {
int other = (i + index) % (number + 1);
if (waits[other] != acquire[other]) {
return true;
}
}
return false;
}
private int notifyWhichRoom() {
for (int i = 1; i <= number; ++i) {
int index = (i + currRoom) % (number + 1);
if (waits[index] != acquire[index]) {
return index;
}
}
return -1;
}
public void enter(int i) {
if (i < 0 || i > number) {
return;
}
lock.lock();
try {
++waits[i];
while (toWait(i)) {
conditions[i].await();
}
++acquire[i];
currRoom = i;
System.out.println("Enter " + i + " room.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public boolean exit() {
if (currRoom == -1) {
return false;
}
lock.lock();
System.out.println("Exit " + currRoom + " room");
++leave[currRoom];
if (leave[currRoom] == acquire[currRoom]) {
if (handlers[currRoom] != null) {
handlers[currRoom].onEmpty();
}
int index = notifyWhichRoom();
if (index >= 0) {
conditions[index].signalAll();
}
currRoom = -1;
}
lock.unlock();
return true;
}
public void setExitHandler(int i, Handler handler) {
if (i < 0 || i > number) {
return;
}
lock.lock();
handlers[i] = handler;
lock.unlock();
}
public interface Handler {
void onEmpty();
}
}
测试示例:
public class TestRoomsThread extends Thread {
private Rooms rooms;
private int index;
public TestRoomsThread(Rooms rooms, int index) {
this.rooms = rooms;
this.index = index;
}
@Override
public void run() {
rooms.enter(index);
}
}
private static void test_rooms() {
Rooms rooms = new Rooms(2);
rooms.setExitHandler(0, new Rooms.Handler() {
@Override
public void onEmpty() {
System.out.println("0 room is empty");
}
});
rooms.setExitHandler(1, new Rooms.Handler() {
@Override
public void onEmpty() {
System.out.println("1 room is empty");
}
});
TestRoomsThread tester1 = new TestRoomsThread(rooms, 0);
TestRoomsThread tester2 = new TestRoomsThread(rooms, 0);
TestRoomsThread tester3 = new TestRoomsThread(rooms, 1);
tester1.start();
tester2.start();
tester3.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
rooms.exit();
rooms.exit();
}
测试结果:
(1)并发执行tester1,tester2,tester3,没有线程退出房间,执行结果:线程tester1,tester2进入房间0;线程test3不能进入房间1.
(2)并发执行线程tester1,tester2,tester3,线程tester1,tetser2退出房间0,执行结果:当线程tester1,tester2退出房间后,线程tester3才能进入房间。