Пример #1
0
 @OverrideMustInvoke
 @Activate
 protected void activate(Map<String, Object> props) {
   // configuring the buffer
   Integer bufferSize = Integer.valueOf(200);
   if (props.containsKey(BUFFER_SIZE)) {
     bufferSize = (Integer) props.get(BUFFER_SIZE);
   }
   this.fifo = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(bufferSize));
 }
Пример #2
0
/**
 * This class manages worker threads. Its main responsibility is to create / remove worker threads
 * and distribute tasks among them. This is an effort to hide complexity of threading logic from the
 * rest of toolkit. Worker manager receives processing requests from external tools and assigns them
 * to free worker threads. If there's no free worker thread left manager puts item in queue. When
 * worker thread finishes its job it asks for next job using <code>JobSource</code> callback
 * interface. If there is at least one job in queue manager assigns it to worker. If not then worker
 * goes to rest until manager has something to assign.
 *
 * <p>Worker manager uses instance of <code>WorkerThreadFactoryIF</code> specified on creation to
 * create new worker threads. Client application should use it to create and initialize
 * task-specific workers, which will be started as independent threads.
 *
 * <p>It's possible to tune number of threads working at a given time using <code>
 * setWorkerThreads(int)</code> method call. Right after the number of threads will change manager
 * will stop unnecessary threads (only after running task completion) or create new worker threads.
 *
 * @author Aleksey Gureev ([email protected])
 */
public class WorkersManager {
  private static final int DEFAULT_WORKER_THREADS = 5;
  private static final int DEFAULT_QUEUE_LIMIT = 25;

  private List<WorkerThread> workers = new ArrayList<>();

  // This code intentionally uses deprecated classes! Old commons library was 150 Kb and
  // current is 550 Kb. Many applications (including BlogBridge) will be enforced to replace
  // small lib with giantic new one if we start using new classes instead these.
  // When support of these will be finished, please replace:
  //    PriorityQueue             -> Buffer
  //    SynchronizedPriorityQueue -> SynchronizedBuffer
  //    BinaryHeap                -> PriorityBuffer
  private Buffer queue =
      BufferUtils.blockingBuffer(new BinaryHeap(DEFAULT_QUEUE_LIMIT, new PriorityComparator()));

  private WorkerThreadFactoryIF workerThreadsFactory;

  /**
   * Creates worker manager with default number of worker threads.
   *
   * @param factory worker threads factory.
   */
  public WorkersManager(WorkerThreadFactoryIF factory) {
    this(factory, DEFAULT_WORKER_THREADS);
  }

  /**
   * Creates worker manager.
   *
   * @param factory worker threads factory.
   * @param workerThreads number of worker threads.
   */
  public WorkersManager(WorkerThreadFactoryIF factory, int workerThreads) {
    this.workerThreadsFactory = factory;

    // Protect ourselves from incorrect parameters.
    if (workerThreads <= 0) {
      workerThreads = DEFAULT_WORKER_THREADS;
    }

    setWorkerThreads(workerThreads);
  }

  /**
   * Changes number of worker threads.
   *
   * @param count new number of worker threads.
   */
  public final void setWorkerThreads(int count) {
    synchronized (workers) {
      // If we have more than specified number of working threads then terminate unwanted.
      int curWorkerThreads = workers.size();
      for (int i = curWorkerThreads - 1; i >= count; i--) {
        final WorkerThread worker = workers.get(i);
        worker.terminate();
        workers.remove(worker);
      }

      // If we have less than specified number of thread then add some.
      curWorkerThreads = workers.size();
      for (int i = curWorkerThreads; i < count; i++) {
        // Create new worker using custom factory.
        final WorkerThread worker = workerThreadsFactory.create();
        worker.setQueue(queue);

        // Add worker to the list and start.
        workers.add(worker);
        worker.start();
      }
    }
  }

  /** Terminates all worker threads. */
  public final void terminateAll() {
    synchronized (workers) {
      int count = workers.size();
      for (int i = count - 1; i >= 0; i--) {
        workers.get(i).terminate();
        workers.remove(i);
      }
    }
  }

  /**
   * Put the record in processing.
   *
   * @param record record to process.
   */
  public final void process(ChannelRecord record) {
    if (!isInProcess(record)) {
      putRecordInQueue(record);
    }
  }

  /**
   * Checks if the channel is not currently in processing.
   *
   * @param record channel record.
   * @return TRUE if is in processing.
   */
  private boolean isInProcess(ChannelRecord record) {
    boolean found = false;

    synchronized (workers) {
      Iterator<WorkerThread> i = workers.iterator();
      while (!found && i.hasNext()) {
        WorkerThread worker = i.next();
        found = worker.getChannelInProcess() == record;
      }
    }

    return found;
  }

  /**
   * Put task in processing queue. During putting the task algorythm analyzes the priority of
   * insertion and evaluates index of new item in queue.
   *
   * @param record record to put in queue.
   */
  @SuppressWarnings("unchecked")
  private void putRecordInQueue(ChannelRecord record) {
    queue.add(record);
  }
}