我有以下情景
大楼里有一个洗手间
它将有2种类型[截至目前]的厕所。 MALE
和FEMALE
,其数量为n。
如果一群人进入洗手间。我希望他们尽可能占用最多的房间。
假设有20人一次进入洗手间,使用以下组合
People 20
Male 10 Female 10
RestRoom Avaialbiltiy
MALE 2
FEMALE 1
有些人会花更多的时间,所以下一个人必须排队等候。male
无法进入female
厕所,反之亦然。
对于上述情况,我已经扩展了ThreadpoolExecutor
并逐个添加Person
,并且只要匹配的厕所是可用的,请立即分配。
所以这是示例的MCVE。我想检查这是否是在ThreadPool中处理条件的正确方法
RestRoom.java
import java.util.HashMap;
import java.util.Map;
public enum RestRoom {
MALE,
FEMALE;//will extend for ex [Differently Abled]
public int maxInstance = 0;
public RestRoom withMaxInstance(int maxInstance) {
this.maxInstance = maxInstance;
return this;
}
public static int getTotalNoOfRestRooms() {
int count = 0;
for (RestRoom room : RestRoom.values()) {
count += room.maxInstance;
}
return count;
}
public static Map<RestRoom, Integer> getAvailabiltyAsMap() {
Map<RestRoom, Integer> avaialbilty = new HashMap<>();
for (RestRoom room : RestRoom.values()) {
avaialbilty.put(room, room.maxInstance);
}
return avaialbilty;
}
}
Person.java(Runnable)
import java.util.logging.Level;
import java.util.logging.Logger;
public class Person implements Runnable {
private final String name;
private final RestRoom gender;
private int second;
public Person(String name, RestRoom gender) {
this.name = name;
this.gender = gender;
}
public Person withTime(int second) {
this.second = second;
return this;
}
@Override
public void run() {
try {
System.out.println("Running " + name + " with " + gender);
Thread.sleep(second * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(Person.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getName() {
return name;
}
public RestRoom getGender() {
return gender;
}
@Override
public String toString() {
return "Person{" + "name=" + name + ", gender=" + gender + '}';
}
}
CustomThreadPool.java
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CustomThreadPool extends ThreadPoolExecutor {
Map<RestRoom, Integer> avaialbilty = new HashMap<>();
LinkedBlockingDeque<Runnable> remaining = new LinkedBlockingDeque<>();
public CustomThreadPool(int corePoolSize, long keepAliveTime) {
super(corePoolSize, corePoolSize, keepAliveTime, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>());
avaialbilty = RestRoom.getAvailabiltyAsMap();
}
@Override
protected void afterExecute(Runnable runnable, Throwable throwable) {
avaialbilty.put(getRestRoomFor(runnable), avaialbilty.get(getRestRoomFor(runnable)) + 1);
for (int i = 0; i < remaining.size(); i++) {
execute(remaining.remove());
}
if (remaining.isEmpty()) {
shutdown();
}
}
@Override
public void execute(Runnable runnable) {
if (avaialbilty.get(getRestRoomFor(runnable)) > 0) {
avaialbilty.put(getRestRoomFor(runnable), avaialbilty.get(getRestRoomFor(runnable)) - 1);
super.execute(runnable);
} else {
remaining.add(runnable);
}
}
private RestRoom getRestRoomFor(Runnable runnable) {
return asPerson(runnable).getGender();
}
private Person asPerson(Runnable runnable) {
return (Person) runnable;
}
}
Test.java
public class Test {
public static void main(String[] args) {
RestRoom.MALE.withMaxInstance(3);
RestRoom.FEMALE.withMaxInstance(2);
CustomThreadPool threadPool = new CustomThreadPool(RestRoom.getTotalNoOfRestRooms(), 2);
for (int i = 0; i < 10; i++) {
threadPool.execute(new Person("M" + i, RestRoom.MALE).withTime(2));
threadPool.execute(new Person("F" + i, RestRoom.FEMALE).withTime(1));
}
}
}