nraynaud lol | cerisier > oui, passé le timeout en macro, lazy instanciation du timer et du thread de pompage et un commentaire :
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 Thread executor;
- /**
- * the big one scheduler
- */
- private static NetworkScheduler instance = null;
- public static synchronized NetworkScheduler getInstance() {
- if (instance == null)
- instance = new NetworkScheduler();
- return instance;
- }
- private NetworkScheduler() {
- }
- private void alertExecutor() {
- assert (Thread.holdsLock(this));
- if (executor == null)
- executor = new WorkingThread();
- synchronized (executor) {
- executor.notify();
- }
- }
- 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;
- }
- /**
- * 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
- *
- * get a task from the queue and execute it. If the task takes more than 15
- * seconds to execute, a new thread is raised to flush-execute the task
- * queue and this one is left to die.
- */
- private final class WorkingThread extends Thread {
- private volatile boolean terminate = false;
- private WorkingThread() {
- super("network" );
- this.setDaemon(true);
- this.start();
- incrementThreadnumber();
- System.out.println("working threads : " + threadNumber);
- }
- /**
- * blocks the thread until notified.
- *
- */
- private synchronized void waitForNotification() {
- try {
- wait();
- } catch (InterruptedException e) {
- //continue
- }
- }
- public void run() {
- while (!terminate) {
- 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);
- }
- /**
- * Executes the given task, using a timeout. If the time is over, a new
- * executor is created to fetch the work queue.
- */
- private void executeTask(final Task task) {
- TimerTask timeoutTask = new TimerTask() {
- public void run() {
- System.out.println("notice : task timeout : "
- + task.toString());
- terminate = true;
- assert (executor == WorkingThread.this);
- assert (task != null);
- executor = new WorkingThread();
- }
- };
- executingTasks.add(task);
- getTimer().schedule(timeoutTask, MAX_EXECUTION_TIME);
- try {
- task.work();
- } catch (Exception e) {
- task.onException(e);
- } finally {
- timeoutTask.cancel();
- executingTasks.remove(task);
- }
- }
- }
- }
|
---------------
trainoo.com, c'est fini
|