Custom Execution Service for event loop basic implementation
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
package mc.core.events.v3.runner;
|
||||||
|
|
||||||
|
import sun.plugin.dom.exception.InvalidStateException;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
|
public class EventExecutorService {
|
||||||
|
private BlockingQueue<ResourceRunnable> queue = new ArrayBlockingQueue<>(100);
|
||||||
|
private ScheduleStrategy strategy = new DefaultScheduleStrategy();
|
||||||
|
private Set<Thread> executorThreads = new HashSet<>();
|
||||||
|
private int threadCount;
|
||||||
|
|
||||||
|
public EventExecutorService(int threadCount) {
|
||||||
|
this.threadCount = threadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
if (executorThreads.size() > 0)
|
||||||
|
throw new InvalidStateException("This executor service was already started.");
|
||||||
|
|
||||||
|
for (int i = 0; i < threadCount; i++) {
|
||||||
|
Thread thread = new ExecutorThread("Event Loop #" + i, this);
|
||||||
|
executorThreads.add(thread);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
if (executorThreads.size() == 0)
|
||||||
|
throw new InvalidStateException("This executor service was not initialized yet.");
|
||||||
|
|
||||||
|
Iterator<Thread> iterator = executorThreads.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Thread thread = iterator.next();
|
||||||
|
thread.interrupt();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTask(ResourceRunnable task) {
|
||||||
|
if (Thread.currentThread() instanceof ExecutorThread) {
|
||||||
|
// TODO: Do we really need instant execution?
|
||||||
|
((ExecutorThread) Thread.currentThread()).executeTask(task);
|
||||||
|
} else
|
||||||
|
queue.offer(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ScheduleStrategy getStrategy() {
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefaultScheduleStrategy implements ScheduleStrategy {
|
||||||
|
public ResourceRunnable getTask() throws InterruptedException {
|
||||||
|
return queue.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package mc.core.events.v3.runner;
|
||||||
|
|
||||||
|
public class ExecutorThread extends Thread {
|
||||||
|
private EventExecutorService service;
|
||||||
|
|
||||||
|
public ExecutorThread(String name, EventExecutorService service) {
|
||||||
|
super(name);
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!isInterrupted() && isAlive()) {
|
||||||
|
ResourceRunnable runnable;
|
||||||
|
try {
|
||||||
|
runnable = service.getStrategy().getTask();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
executeTask(runnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeTask(ResourceRunnable runnable) {
|
||||||
|
runnable.lock();
|
||||||
|
try {
|
||||||
|
runnable.run();
|
||||||
|
} finally {
|
||||||
|
runnable.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package mc.core.events.v3.runner;
|
||||||
|
|
||||||
|
public interface ResourceRunnable extends Runnable {
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
void unlock();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package mc.core.events.v3.runner;
|
||||||
|
|
||||||
|
public interface ScheduleStrategy {
|
||||||
|
ResourceRunnable getTask() throws InterruptedException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package ru.core.events.v3;
|
||||||
|
|
||||||
|
import mc.core.events.v3.runner.EventExecutorService;
|
||||||
|
import mc.core.events.v3.runner.ResourceRunnable;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class EventExecutorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void basicTest() throws InterruptedException {
|
||||||
|
AtomicBoolean testVariable = new AtomicBoolean(false);
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
EventExecutorService service = new EventExecutorService(1);
|
||||||
|
service.start();
|
||||||
|
service.addTask(new ResourceRunnable() {
|
||||||
|
@Override
|
||||||
|
public void lock() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
testVariable.set(true);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
latch.await(1, TimeUnit.SECONDS);
|
||||||
|
service.stop();
|
||||||
|
Assert.assertTrue("Scheduled task was not executed", testVariable.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user