nraynaud lol | Code :
- /*
- * Created on 23 avr. 2004
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
- package jcoincoin.net;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.LinkedList;
- import java.util.Map;
- import java.util.NoSuchElementException;
- import java.util.Set;
- import java.util.Timer;
- import java.util.TimerTask;
- /**
- * @author nraynaud
- *
- * Represents a very simple time slicer. Using this avoid having lots of threads
- * in the system using the network randomly.
- *
- * Units of work are represented by the Task interface. If the work takes more
- * than a certain amouth of time to complete, a second Thread is created to
- * continue fetching work out of the queue.
- *
- */
- public class NetworkScheduler {
- /**
- * the time a task can run before we start a second thread to process the
- * queue.
- */
- private static final int MAX_EXECUTION_TIME = 10000;
- /**
- * the great task queue
- */
- private LinkedList taskQueue = new LinkedList();
- /**
- * the big timer used for periodicity.
- */
- private Timer timer = null;
- /**
- * the hashmap Task -> PeriodicTask of the curently registered periodic
- * tasks.
- */
- private final Map periodicTasksMap = new HashMap();
- /**
- * number of threads to process the task queue.
- */
- static private volatile int threadNumber = 0;
- static private synchronized void incrementThreadnumber() {
- threadNumber++;
- }
- static private synchronized void decrementThreadnumber() {
- threadNumber--;
- }
- private Set executingTasks = new HashSet();
- /**
- * current main executor.
- */
- private WorkingThread currentExecutor;
- /**
- * the big one scheduler
- */
- private static NetworkScheduler instance = null;
- private TimerTask timeoutTask;
- public static synchronized NetworkScheduler getInstance() {
- if (instance == null)
- instance = new NetworkScheduler();
- return instance;
- }
- private NetworkScheduler() {
- }
- private void alertExecutor() {
- assert (Thread.holdsLock(this));
- getCurrentExecutor().alertNewMessage();
- }
- /**
- *
- * @return the current executor, creating a new one if there is none.
- */
- private synchronized WorkingThread getCurrentExecutor() {
- if (currentExecutor == null)
- currentExecutor = new WorkingThread();
- return currentExecutor;
- }
- private synchronized void setCurrentExecutor(WorkingThread ex) {
- currentExecutor = ex;
- }
- private synchronized void timeoutCurrentExecutor() {
- System.out.println("notice : task timeout : "
- + String.valueOf(getCurrentExecutor().getCurrentTask()));
- getCurrentExecutor().timeout();
- setCurrentExecutor(new WorkingThread());
- }
- private synchronized Task getTask() {
- try {
- return (Task) taskQueue.removeFirst();
- } catch (NoSuchElementException e) {
- return null;
- }
- }
- /**
- * Immediately enqueue the given task for execution.
- *
- * @param task
- * the task to enqueue.
- */
- public synchronized void enqueue(Task task) {
- taskQueue.addLast(task);
- alertExecutor();
- }
- /**
- * Enqueue th task to be executed exactly at the end of the currently
- * executing task. This means that unfair enqueuing are unfair betwen
- * themselves too, this is not a priority scheme.
- *
- * @param task
- * the work
- */
- public synchronized void unfairlyEnqueue(Task task) {
- taskQueue.addFirst(task);
- alertExecutor();
- }
- /**
- * Schedules the given task to be enqueued regulary at the given period.
- * Exactly, the task is sceduled to be reenqueued period millisecond after
- * the end of it's execution. The task is first immediately enqueued.
- *
- * @param task
- * the work unit.
- * @param period
- * the period in milliseconds.
- */
- synchronized public void periodicalyEnqueue(final Task task,
- final long period) {
- PeriodicTask pTask = new PeriodicTask(task, period);
- periodicTasksMap.put(task, pTask);
- enqueue(pTask);
- }
- synchronized public void changePeriod(Task task, final long newPeriod) {
- PeriodicTask pTask = (PeriodicTask) periodicTasksMap.get(task);
- if (pTask == null)
- throw new IllegalArgumentException(
- "the given task is not in the system" );
- else
- pTask.setPeriod(newPeriod);
- }
- synchronized public void removePeriodicTask(Task task) {
- if (periodicTasksMap.remove(task) == null)
- throw new IllegalArgumentException(
- "the given task is not in the system" );
- }
- /**
- * Enqueues the given task after the given period.
- *
- * @param task
- * the task to reenqueue
- * @param delay
- * the delay to wait in milliseconds.
- */
- private void enqueueDelayed(final Task task, final long delay) {
- getTimer().schedule(new TimerTask() {
- public void run() {
- enqueue(task);
- }
- }, delay);
- }
- private synchronized Timer getTimer() {
- if (timer == null)
- timer = new Timer(true);
- return timer;
- }
- /**
- * Excutor listening infrastructure.
- *
- * @param t
- * @param e
- */
- private synchronized void startTask(Task t, WorkingThread e) {
- assert (e == getCurrentExecutor());
- timeoutTask = new TimerTask() {
- public void run() {
- timeoutCurrentExecutor();
- }
- };
- getTimer().schedule(timeoutTask, MAX_EXECUTION_TIME);
- }
- /**
- * Executor listening infrastructure.
- *
- * @param t
- * @param e
- */
- private synchronized void endTask(Task t, WorkingThread e) {
- if (e == getCurrentExecutor())
- timeoutTask.cancel();
- }
- /**
- * Periodic Task proxy.
- *
- * @author nraynaud
- *
- */
- private class PeriodicTask implements Task {
- private final Task task;
- volatile private long period;
- /**
- * @param task
- * @param period
- */
- public PeriodicTask(final Task task, long period) {
- this.task = task;
- this.period = period;
- }
- public void work() {
- try {
- task.work();
- } finally {
- synchronized (NetworkScheduler.this) {
- if (periodicTasksMap.get(task) == this)
- enqueueDelayed(this, period);
- }
- }
- }
- public String toString() {
- return task.toString() + " (made periodic)";
- }
- public void onException(Exception e) {
- task.onException(e);
- }
- public boolean equals(Object other) {
- return task.equals(other);
- }
- public int hashCode() {
- return task.hashCode();
- }
- /**
- * @return Returns the period.
- */
- synchronized public long getPeriod() {
- return period;
- }
- /**
- * @param period
- * The period to set.
- */
- synchronized public void setPeriod(long period) {
- this.period = period;
- }
- }
- /**
- * @author nraynaud
- *
- * The executor is responsible for fetching tasks and executing them. If it
- * as been timeouted, it will die after finishig the current task.
- */
- private final class WorkingThread {
- /**
- * should we continue threating the queue ?
- */
- private volatile boolean timeout = false;
- /**
- * the real thread. note that it will be used as the lock-key only
- * because its lifetime is the same as the Executor's one and it is not
- * publicly visible (so no one can interfere with the notification
- * system).
- */
- private final Thread thread;
- private Task currentTask = null;
- private WorkingThread() {
- thread = new Thread(new Runnable() {
- public void run() {
- incrementThreadnumber();
- while (!timeout) {
- Task task = getTask();
- if (task == null)
- waitForNotification();
- else if (!executingTasks.contains(task))
- executeTask(task);
- else
- System.out.println("task :" + task
- + "already running" );
- }
- decrementThreadnumber();
- System.out.println("working threads : " + threadNumber);
- }
- private synchronized void waitForNotification() {
- try {
- synchronized (thread) {
- thread.wait();
- }
- } catch (InterruptedException e) {
- //continue
- }
- }
- });
- thread.setName("network " + threadNumber);
- thread.setDaemon(true);
- thread.start();
- System.out.println("working threads : " + threadNumber);
- }
- /**
- * @return
- */
- public Task getCurrentTask() {
- return currentTask;
- }
- /**
- * tells this executor it took too long to complete.
- *
- */
- public void timeout() {
- timeout = true;
- }
- /**
- * called to alert that a new message entered the queue.
- */
- public void alertNewMessage() {
- synchronized (thread) {
- thread.notify();
- }
- }
- /**
- * Executes the given task.
- */
- private void executeTask(final Task task) {
- currentTask = task;
- synchronized (NetworkScheduler.this) {
- startTask(task, this);
- executingTasks.add(task);
- }
- try {
- task.work();
- } catch (Exception e) {
- task.onException(e);
- } finally {
- synchronized (NetworkScheduler.this) {
- executingTasks.remove(task);
- endTask(task, this);
- }
- currentTask = null;
- }
- }
- }
- }
|
c'est nul, il a gagné 67 lignes et pas une seule fonctionnalité.
edit : et puis c'est tout nul, à part l'idée de pas soucalsser Thread et l'idée de pas exposerle mécanisme de wait/notify inutilement, le reste est nul (sortir le timeout par ex. ou le faux observateur). Message édité par nraynaud le 31-07-2004 à 00:38:11 ---------------
trainoo.com, c'est fini
|