Initial implementation of Worker and Listener using Executor framework
This commit is contained in:
9
java/base/src/main/java/base/worker/AbstractWorker.java
Normal file
9
java/base/src/main/java/base/worker/AbstractWorker.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package base.worker;
|
||||
|
||||
public abstract class AbstractWorker {
|
||||
public abstract void start();
|
||||
|
||||
public abstract void stop();
|
||||
|
||||
protected abstract void work();
|
||||
}
|
||||
38
java/base/src/main/java/base/worker/pooled/ListenerPool.java
Normal file
38
java/base/src/main/java/base/worker/pooled/ListenerPool.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ListenerPool<E> {
|
||||
protected int poolSize;
|
||||
protected BlockingQueue<Wrapper<E>> queue;
|
||||
protected ExecutorService executorService;
|
||||
|
||||
public ListenerPool(int poolSize) {
|
||||
this.poolSize = poolSize;
|
||||
queue = new SynchronousQueue<Wrapper<E>>();
|
||||
executorService = Executors.newFixedThreadPool(poolSize);
|
||||
}
|
||||
|
||||
public PooledListener<E> add(PooledListener<E> listener) {
|
||||
listener.setPoolQueue(queue);
|
||||
return listener;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (int i = 0; i < poolSize; ++i) {
|
||||
Runnable runnable = new ListenerPoolRunnable<E>(queue, i);
|
||||
executorService.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void await() {
|
||||
try {
|
||||
executorService.awaitTermination(0, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
class ListenerPoolRunnable<E> implements Runnable {
|
||||
protected BlockingQueue<Wrapper<E>> queue;
|
||||
protected int id;
|
||||
|
||||
public ListenerPoolRunnable(BlockingQueue<Wrapper<E>> queue, int id) {
|
||||
this.queue = queue;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
System.out.println("Thread #" + id + " waiting...");
|
||||
Wrapper<E> wrapper = queue.take();
|
||||
wrapper.deliver();
|
||||
Thread.sleep((int) (Math.random() * 1000));
|
||||
}
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public abstract class PooledListener<E> {
|
||||
protected BlockingQueue<Wrapper<E>> poolQueue;
|
||||
|
||||
public void setPoolQueue(BlockingQueue<Wrapper<E>> poolQueue) {
|
||||
this.poolQueue = poolQueue;
|
||||
}
|
||||
|
||||
public synchronized void add(E element) {
|
||||
Wrapper<E> wrapper = new Wrapper<E>(this, element);
|
||||
poolQueue.add(wrapper);
|
||||
}
|
||||
|
||||
abstract void input(E element);
|
||||
}
|
||||
40
java/base/src/main/java/base/worker/pooled/PooledWorker.java
Normal file
40
java/base/src/main/java/base/worker/pooled/PooledWorker.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import base.worker.Worker;
|
||||
|
||||
public abstract class PooledWorker extends Worker {
|
||||
protected BlockingQueue<Worker> activateQueue;
|
||||
protected BlockingQueue<Worker> deactivateQueue;
|
||||
|
||||
public void setActivateQueue(BlockingQueue<Worker> activateQueue) {
|
||||
this.activateQueue = activateQueue;
|
||||
}
|
||||
|
||||
public void setDeactivateQueue(BlockingQueue<Worker> deactivateQueue) {
|
||||
this.deactivateQueue = deactivateQueue;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (!active) {
|
||||
activate = true;
|
||||
}
|
||||
if (!run) {
|
||||
run = true;
|
||||
}
|
||||
try {
|
||||
deactivateQueue.remove(this);
|
||||
activateQueue.put(this);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
System.out.println("stop!! " + active);
|
||||
if (active) {
|
||||
deactivate = true;
|
||||
}
|
||||
activateQueue.remove(this);
|
||||
deactivateQueue.add(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TestPooledListener extends PooledListener<Integer> {
|
||||
protected int id;
|
||||
|
||||
public TestPooledListener(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void input(Integer element) {
|
||||
System.out.println("#" + id + ": " + element);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ListenerPool<Integer> listenerPool = new ListenerPool<Integer>(5);
|
||||
List<PooledListener<Integer>> listenerList = new ArrayList<PooledListener<Integer>>();
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
PooledListener<Integer> pooledListener = listenerPool.add(new TestPooledListener(i + 1));
|
||||
listenerList.add(pooledListener);
|
||||
}
|
||||
|
||||
listenerPool.start();
|
||||
|
||||
System.out.println("Starting to give out elements!");
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
PooledListener<Integer> randomListener = listenerList.get((new Random()).nextInt(listenerList.size()));
|
||||
randomListener.add(i);
|
||||
}
|
||||
|
||||
//listenerPool.await();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import base.exception.worker.ActivateException;
|
||||
import base.exception.worker.DeactivateException;
|
||||
import base.worker.Worker;
|
||||
|
||||
public class TestPooledWorker extends PooledWorker {
|
||||
protected int id;
|
||||
protected volatile int work;
|
||||
|
||||
public TestPooledWorker(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
protected void setWork(int work) {
|
||||
System.out.println("#" + id + ", set work @ " + work);
|
||||
this.work = work;
|
||||
}
|
||||
|
||||
public void work() {
|
||||
System.out.println("#" + id + ", work = " + work);
|
||||
if (--work < 1) {
|
||||
stop();
|
||||
}
|
||||
sleep(300);
|
||||
}
|
||||
|
||||
protected void activate() throws ActivateException {
|
||||
System.out.println("#" + id + ", activating...");
|
||||
super.activate();
|
||||
}
|
||||
|
||||
protected void deactivate() throws DeactivateException {
|
||||
super.deactivate();
|
||||
System.out.println("#" + id + ", deactivating...");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
WorkerPool workerPool = new WorkerPool(3);
|
||||
|
||||
List<TestPooledWorker> workerList = new ArrayList<TestPooledWorker>();
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
TestPooledWorker worker = new TestPooledWorker(i + 1);
|
||||
workerPool.add(worker);
|
||||
workerList.add(worker);
|
||||
}
|
||||
workerPool.start();
|
||||
|
||||
System.out.println("Starting work!");
|
||||
int work = 1000;
|
||||
ArrayList<Worker> activeWorkerList = new ArrayList<Worker>();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestPooledWorker worker = workerList.get((new Random()).nextInt(workerList.size()));
|
||||
worker.setWork(work);
|
||||
worker.start();
|
||||
activeWorkerList.add(worker);
|
||||
}
|
||||
int i = 0;
|
||||
|
||||
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
for (Worker worker : activeWorkerList) {
|
||||
if (++i > 5) {
|
||||
break;
|
||||
}
|
||||
worker.stop();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100000);
|
||||
} catch (InterruptedException e) {}
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
42
java/base/src/main/java/base/worker/pooled/WorkerPool.java
Normal file
42
java/base/src/main/java/base/worker/pooled/WorkerPool.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import base.util.ArrayCycle;
|
||||
import base.worker.Worker;
|
||||
|
||||
public class WorkerPool {
|
||||
protected int poolSize;
|
||||
protected BlockingQueue<Worker> activateQueue;
|
||||
protected BlockingQueue<Worker> deactivateQueue;
|
||||
protected ArrayCycle<Worker> workerCycle;
|
||||
protected ExecutorService executorService;
|
||||
|
||||
public WorkerPool(int poolSize) {
|
||||
this.poolSize = poolSize;
|
||||
activateQueue = new LinkedBlockingQueue<Worker>();
|
||||
deactivateQueue = new LinkedBlockingQueue<Worker>();
|
||||
workerCycle = new ArrayCycle<Worker>();
|
||||
executorService = Executors.newFixedThreadPool(poolSize);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (int i = 0; i < poolSize; ++i) {
|
||||
Runnable runnable = new WorkerPoolRunnable(activateQueue, deactivateQueue, workerCycle, i + 1);
|
||||
executorService.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
// Must be graceful
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
public void add(PooledWorker worker) {
|
||||
worker.setActivateQueue(activateQueue);
|
||||
worker.setDeactivateQueue(deactivateQueue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import base.util.ArrayCycle;
|
||||
import base.worker.Worker;
|
||||
|
||||
public class WorkerPoolRunnable implements Runnable {
|
||||
protected BlockingQueue<Worker> activateQueue;
|
||||
protected BlockingQueue<Worker> deactivateQueue;
|
||||
protected ArrayCycle<Worker> workerCycle;
|
||||
protected int id;
|
||||
|
||||
public WorkerPoolRunnable(BlockingQueue<Worker> activateQueue, BlockingQueue<Worker> deactivateQueue, ArrayCycle<Worker> workerCycle, int id) {
|
||||
this.activateQueue = activateQueue;
|
||||
this.deactivateQueue = deactivateQueue;
|
||||
this.workerCycle = workerCycle;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
if (!deactivateQueue.isEmpty()) {
|
||||
try {
|
||||
Worker worker = deactivateQueue.take();
|
||||
worker.runDeactivate();
|
||||
workerCycle.remove(worker);
|
||||
} catch (InterruptedException e) {}
|
||||
} else if (!activateQueue.isEmpty() || workerCycle.isEmpty()) {
|
||||
try {
|
||||
Worker worker = activateQueue.take();
|
||||
worker.runActivate();
|
||||
workerCycle.add(worker);
|
||||
} catch (InterruptedException e) {}
|
||||
} else {
|
||||
Worker worker = workerCycle.next();
|
||||
worker.work();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
java/base/src/main/java/base/worker/pooled/Wrapper.java
Normal file
16
java/base/src/main/java/base/worker/pooled/Wrapper.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package base.worker.pooled;
|
||||
|
||||
|
||||
class Wrapper<E> {
|
||||
protected PooledListener<E> listener;
|
||||
protected E element;
|
||||
|
||||
public Wrapper(PooledListener<E> listener, E element) {
|
||||
this.listener = listener;
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public void deliver() {
|
||||
listener.input(element);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user