001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.wake.impl;
020
021import org.apache.reef.wake.AbstractEStage;
022import org.apache.reef.wake.EventHandler;
023
024import java.util.List;
025import java.util.concurrent.ExecutorService;
026import java.util.concurrent.Executors;
027import java.util.concurrent.TimeUnit;
028import java.util.logging.Logger;
029
030/**
031 * This stage uses a thread pool to schedule events in parallel.
032 * Should be used when input events are already materialized in a List and
033 * can be fired in any order.
034 *
035 * @param numThreads  fixed number of threads available in the pool
036 * @param granularity maximum number of events executed serially. The right choice will balance task spawn overhead with parallelism.
037 */
038public class IndependentIterationsThreadPoolStage<T> extends AbstractEStage<List<T>> {
039
040  final private int granularity;
041  private EventHandler<T> handler;
042  private ExecutorService executor;
043
044  public IndependentIterationsThreadPoolStage(EventHandler<T> handler, int numThreads, int granularity) {
045    super(handler.getClass().getName());
046    this.handler = handler;
047    this.executor = Executors.newFixedThreadPool(numThreads);
048    this.granularity = granularity;
049  }
050
051  private Runnable newTask(final List<T> iterations) {
052    return new Runnable() {
053      @Override
054      public void run() {
055        for (T e : iterations) {
056          handler.onNext(e);
057        }
058      }
059    };
060  }
061
062  @Override
063  public void onNext(final List<T> iterations) {
064    Logger.getAnonymousLogger().info("Execute new task [" + iterations.size());
065    final int size = iterations.size();
066    for (int i = 0; i < size; i += granularity) {
067      int toIndex = i + granularity;
068      toIndex = toIndex > size ? size : toIndex;
069      executor.execute(newTask(iterations.subList(i, toIndex)));
070    }
071  }
072
073  @Override
074  public void close() throws Exception {
075    executor.shutdown();
076    executor.awaitTermination(1000, TimeUnit.DAYS);
077  }
078
079
080}