-
-
Save Miha22/3d39697ce947f01886833572ff99e0d5 to your computer and use it in GitHub Desktop.
package com.hkr; | |
import java.util.ArrayDeque; | |
import java.util.Deque; | |
import java.util.Iterator; | |
import static java.lang.System.out; | |
public class ActivationList { | |
private static final Deque<MethodRequest> dispatchQueue = new ArrayDeque<>(5); | |
public static synchronized void enqueue(MethodRequest methodRequest) { | |
dispatchQueue.addLast(methodRequest); | |
out.println("[Added Method Request]: " + methodRequest.getName() + " to dispatchQueue" + | |
"\nQueue size: " + dispatchQueue.size() + "\n"); | |
} | |
public static synchronized void remove(int id) { | |
dispatchQueue.removeIf(m -> { | |
if(m.getId() == id) { | |
out.println("[Removed Method Request]: " + m.getName() + " from dispatchQueue\n"); | |
return true; | |
} | |
return false; | |
}); | |
} | |
public static Iterator<MethodRequest> getIterator() { | |
return dispatchQueue.iterator(); | |
} | |
} |
package com.hkr; | |
public class Future { | |
private final Object result; | |
private final int statusCode; | |
private final int methodId; | |
public Future(int methodId, Object result, int statusCode) { | |
this.methodId = methodId; | |
this.result = result; | |
this.statusCode = statusCode; | |
} | |
public int getStatusCode() { | |
return statusCode; | |
} | |
public Object getResult() { | |
return result; | |
} | |
public int getMethodId() { | |
return methodId; | |
} | |
@Override | |
public String toString() { | |
return "\t[Future value]: " + result.toString() + | |
"\n\t[MethodID]: " + methodId + | |
"\n\t[Status code]: " + statusCode + "\n"; | |
} | |
} |
package com.hkr; | |
import java.util.Arrays; | |
public class MethodRequest { | |
private final String name; | |
private final int id; | |
private final Object[] parameters; | |
private Future future; | |
private static int counter = 0; | |
private final OnResultReady onResultReady; | |
public MethodRequest(String name, OnResultReady onResultReady, Object... parameters) { | |
this.name = name; | |
this.parameters = Arrays.stream(parameters).toArray(); | |
this.id = counter++; | |
future = null; | |
this.onResultReady = onResultReady; | |
} | |
public MethodRequest(String name, OnResultReady onResultReady) { | |
this(name, onResultReady, new Object[0]); | |
} | |
public String getName() { | |
return name; | |
} | |
public int getId() { | |
return id; | |
} | |
public boolean canRun() { | |
//out.println("Is busy: " + Servant.isBusy(name)); | |
boolean flag = Servant.isBusy(name); | |
//out.println("Is busy: " + flag); | |
return !flag; | |
} | |
public Future call() { | |
return Servant.run(id, name, parameters); | |
} | |
public void setFuture(Future future) { | |
this.future = future; | |
onResultReady.resolve(future); | |
} | |
} |
package com.hkr; | |
import java.util.*; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import static java.lang.System.out; | |
public class Proxy { | |
private static final ArrayList<Thread> threads = new ArrayList<>(10); | |
private static final String[] methodsAvailable = new String[] { "getTimeNow", "getDaysBetween" }; | |
public void showMenu() { | |
out.print("Welcome to public API/Proxy" + | |
"\nChoose method you want to execute: " + printMethods() + | |
"\n\nChoice: " | |
); | |
Scanner scanner = new Scanner(System.in); | |
int choice = scanner.nextInt(); | |
MethodRequest methodRequest = createRequest(choice);// Creating MethodRequest based on choice | |
} | |
public synchronized void generateRequests(int count) { | |
for (int i = 0; i < count; i++) { | |
Thread t = new Thread(() -> { | |
MethodRequest methodRequest = createRequest(new Random().nextInt(2));// Creating MethodRequest based on choice | |
}); | |
t.start(); | |
threads.add(t); | |
} | |
// AtomicBoolean finished = new AtomicBoolean(true); | |
// | |
// threads.forEach(t -> { | |
// try { | |
// t.join(); | |
// } catch (InterruptedException e) { | |
// e.printStackTrace(); | |
// } | |
// if(t.isAlive()) | |
// finished.set(false); | |
// }); | |
// | |
// if(finished.get()) | |
// Scheduler.shutdown(); | |
} | |
private MethodRequest createRequest(int choice) { | |
MethodRequest methodRequest = null; // Creating MethodRequest | |
switch (choice) { | |
case 0: | |
methodRequest = new MethodRequest( | |
"getTimeNow", | |
future -> out.println(future.toString()) | |
); | |
Scheduler.insert(methodRequest);// inserting into ActivationList | |
break; | |
case 1 : | |
methodRequest = new MethodRequest( | |
"getDaysBetween", | |
future -> out.println(future.toString()), | |
new Date( | |
121, Calendar.NOVEMBER, 27 | |
).getTime(), | |
new Date( | |
121, Calendar.DECEMBER, 29 | |
).getTime() | |
); | |
Scheduler.insert(methodRequest);// inserting into ActivationList | |
break; | |
} | |
return methodRequest; | |
} | |
private String printMethods() { | |
StringBuilder stringBuilder = new StringBuilder(2); | |
Arrays.stream(methodsAvailable).forEach(stringBuilder::append); | |
return stringBuilder.toString(); | |
} | |
} |
package com.hkr; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.concurrent.Semaphore; | |
import java.util.concurrent.TimeUnit; | |
import static java.lang.System.out; | |
public class Scheduler { | |
private static final Semaphore semaphore = new Semaphore(5, true); | |
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); | |
private static final ArrayList<Thread> threads = new ArrayList<>(5); | |
static { | |
scheduler.scheduleAtFixedRate(Scheduler::run, 0, 3, TimeUnit.SECONDS); | |
} | |
public static void insert(MethodRequest methodRequest) { | |
try { | |
semaphore.acquire(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
ActivationList.enqueue(methodRequest); | |
} | |
private static synchronized void run() { | |
Iterator<MethodRequest> iterator = ActivationList.getIterator(); | |
while(iterator.hasNext()) { | |
MethodRequest method = iterator.next(); | |
if(method.canRun()) { // can run? | |
Thread t = new Thread(() -> { | |
out.printf("[Request ID]: %d" + | |
"\n[Running]: %s\n\n", method.getId(), method.getName()); | |
ActivationList.remove(method.getId()); // remove/dequeue | |
semaphore.release(); | |
Future future = method.call(); // call | |
method.setFuture(future); | |
}); | |
t.start(); | |
threads.add(t); | |
} | |
else { | |
out.printf("[Request ID]: %d" + | |
"\n[Rescheduling]: %s\n\n", method.getId(), method.getName()); | |
} | |
out.println(">>> Going to next method\n"); | |
} | |
} | |
public static void shutdown() { | |
threads.forEach(thread -> { | |
try { | |
thread.join(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
}); | |
scheduler.shutdown(); | |
} | |
} |
package com.hkr; | |
import java.util.Date; | |
import java.util.concurrent.Semaphore; | |
import java.util.concurrent.TimeUnit; | |
import static java.lang.System.out; | |
public class Servant { | |
private static final Semaphore semaphore1 = new Semaphore(1, false); | |
private static final Semaphore semaphore2 = new Semaphore(1, false); | |
private static String getTimeNow() { | |
try { | |
semaphore1.acquire(); | |
Thread.sleep(5000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
semaphore1.release(); | |
return new Date().toString(); | |
} | |
private static long getDaysBetween(Date date1, Date date2, boolean includeEndDate) { | |
try { | |
semaphore2.acquire(); | |
Thread.sleep(6000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
long millisInDay = 60 * 60 * 24 * 1000; | |
long difference = Math.abs(date1.getTime() - date2.getTime()); | |
long add = millisInDay - (difference % millisInDay);//is used to calculate true number of days, because by default hours, minutes are also counted | |
semaphore2.release(); | |
return TimeUnit.MILLISECONDS.toDays(difference + add) + (includeEndDate ? 1 : 0); | |
} | |
private static boolean isTimeBusy() { | |
return semaphore1.availablePermits() == 0; | |
} | |
private static boolean isBetweenBusy() { | |
return semaphore2.availablePermits() == 0; | |
} | |
public static boolean isBusy(String methodName){ | |
return methodName.equals("getTimeNow") ? isTimeBusy() : isBetweenBusy(); | |
} | |
public static Future run(int methodId, String methodName, Object... parameters) { | |
if(methodName.equals("getTimeNow")) { | |
if(parameters.length != 0) { | |
return new Future(methodId, null, 400); | |
} | |
return new Future(methodId, getTimeNow(), 200); | |
} | |
else if(methodName.equals("getDaysBetween")) { | |
if(parameters.length != 2) | |
return new Future(methodId, null, 400); | |
return new Future(methodId, getDaysBetween(new Date((long)parameters[0]), new Date((long)parameters[1]), false), 200); | |
} | |
return new Future(methodId, null, 400); | |
} | |
} |
Miha22
commented
Nov 28, 2021
Possible output:
[Added Method Request]: getTimeNow to dispatchQueue
Queue size: 1
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 2
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 3
[Added Method Request]: getTimeNow to dispatchQueue
Queue size: 4
[Added Method Request]: getTimeNow to dispatchQueue
Queue size: 5
Going to next method
Going to next method
Going to next method
Going to next method
Going to next method
[Removed Method Request]: getTimeNow from dispatchQueue
[Removed Method Request]: getTimeNow from dispatchQueue
[Removed Method Request]: getTimeNow from dispatchQueue
[Removed Method Request]: getDaysBetween from dispatchQueue
[Removed Method Request]: getDaysBetween from dispatchQueue
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 1
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 2
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 3
[Added Method Request]: getTimeNow to dispatchQueue
Queue size: 4
[Added Method Request]: getDaysBetween to dispatchQueue
Queue size: 5
Going to next method
Going to next method
Going to next method
Going to next method
Going to next method
[Future value]: Sun Nov 28 06:00:07 EET 2021
[MethodID]: 6
[Status code]: 200
Going to next method
Going to next method
Going to next method
Going to next method
Going to next method
[Future value]: 33
[MethodID]: 5
[Status code]: 200
Going to next method
Going to next method
Going to next method
Going to next method
Going to next method
[Future value]: Sun Nov 28 06:00:12 EET 2021
[MethodID]: 7
[Status code]: 200
Going to next method
Going to next method
Going to next method
Going to next method
Going to next method
[Future value]: 33
[MethodID]: 4
[Status code]: 200
Going to next method
[Removed Method Request]: getDaysBetween from dispatchQueue
Going to next method
Going to next method
[Removed Method Request]: getDaysBetween from dispatchQueue
Going to next method
Going to next method
[Future value]: Sun Nov 28 06:00:17 EET 2021
[MethodID]: 0
[Status code]: 200
Going to next method
Going to next method
Going to next method
[Removed Method Request]: getTimeNow from dispatchQueue
Going to next method
Going to next method
[Future value]: 33
[MethodID]: 2
[Status code]: 200
[Future value]: Sun Nov 28 06:00:25 EET 2021
[MethodID]: 9
[Status code]: 200
Going to next method
Going to next method
Going to next method
Going to next method
[Future value]: 33
[MethodID]: 3
[Status code]: 200
Going to next method
Going to next method
[Removed Method Request]: getDaysBetween from dispatchQueue
[Removed Method Request]: getDaysBetween from dispatchQueue
[Future value]: 33
[MethodID]: 1
[Status code]: 200
[Future value]: 33
[MethodID]: 8
[Status code]: 200