@Override public E poll() { queueingStrategy.onBeforeRemove(); E value = null; try { return value = super.poll(); } finally { queueingStrategy.onAfterRemove(value); } }
@Override public boolean add(E e) { queueingStrategy.onBeforeAdd(e); try { return super.add(e); } finally { queueingStrategy.onAfterAdd(); } }
@Override public void put(E e) throws InterruptedException { queueingStrategy.onBeforeAdd(e); try { super.put(e); } finally { queueingStrategy.onAfterAdd(); } }
@Override public E take() throws InterruptedException { queueingStrategy.onBeforeRemove(); E value = null; try { return value = super.take(); } finally { queueingStrategy.onAfterRemove(value); } }
QueueingStrategy<QSTaskModel> queueingStrategy = QueueingStrategies.newHeapQueueingStrategy( configuration.getDouble(QSConfig.PROP_HEAP_STRATEGY_TRIGGER), configuration.getLong(QSConfig.PROP_HEAP_STRATEGY_MAX_DELAY), TaskServiceIterable taskIterable = new TaskServiceIterable(taskService); ExecutorService workerExecutorService = StrategicExecutors.newBalancingThreadPoolExecutor( new ThreadPoolExecutor( configuration.getInt(QSConfig.PROP_WORKER_POOL_CORE), configuration.getInt(QSConfig.PROP_WORKER_POOL_MAX), 1, TimeUnit.MINUTES, new SynchronousQueue<Runnable>(), new CallerBlocksPolicy() ), configuration.getFloat(QSConfig.PROP_WORKER_POOL_UTILIZATION), DEFAULT_SMOOTHING_WEIGHT, DEFAULT_BALANCE_AFTER
/** * Return a capped {@link BalancingThreadPoolExecutor} with the given * maximum number of threads, target utilization, smoothing weight, and * balance after values. * * @param maxThreads maximum number of threads to use * @param targetUtilization a float between 0.0 and 1.0 representing the * percentage of the total CPU time to be used by * this pool * @param smoothingWeight smooth out the averages of the CPU and wait time * over time such that tasks aren't too heavily * skewed with old or spiking data * @param balanceAfter balance the thread pool after this many tasks * have run */ public static BalancingThreadPoolExecutor newBalancingThreadPoolExecutor(int maxThreads, float targetUtilization, float smoothingWeight, int balanceAfter) { ThreadPoolExecutor tpe = new ThreadPoolExecutor(1, maxThreads, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new CallerBlocksPolicy()); return newBalancingThreadPoolExecutor(tpe, targetUtilization, smoothingWeight, balanceAfter); }
@Override protected void go() throws Exception { // If the heap is filling up, this should block for a bit. queueStrategy.on*Remove called when // task processing completes in the WorkerQueueItemHandler. queueingStrategy.onBeforeAdd(null); QSTaskModel task = taskService.getAvailableTask(); taskServices.put(task, taskService); transferQueue.put(task); queueingStrategy.onAfterAdd(); } }
@SuppressWarnings("unchecked") @Override public void onSuccess(QSTaskModel task, TaskKit kit, Object result) { kit.worker.onSuccess(kit.factory, kit, result); queueingStrategy.onBeforeRemove(); taskService.closeTask(task); LOG.info("Task succeeded: {}", task); task.finishedHappy = true; }
/** * Return a capped {@link BalancingThreadPoolExecutor} with the given * maximum number of threads and target utilization. The default smoothing * weight and balance after constants are used. * * @param maxThreads maximum number of threads to use * @param targetUtilization a float between 0.0 and 1.0 representing the * percentage of the total CPU time to be used by * this pool */ public static BalancingThreadPoolExecutor newBalancingThreadPoolExecutor(int maxThreads, float targetUtilization) { return newBalancingThreadPoolExecutor(maxThreads, targetUtilization, DEFAULT_SMOOTHING_WEIGHT, DEFAULT_BALANCE_AFTER); }
@SuppressWarnings("unchecked") @Override public void onComplete(QSTaskModel task, TaskKit kit, Object result) { kit.worker.onComplete(kit.factory, kit, result); task.finished = System.currentTimeMillis(); task.elapsed = task.finished - task.started; logService.completedTask(task); queueingStrategy.onAfterRemove(task); }
/** * Return a StrategicBlockingQueue backed by the given BlockingQueue using * the given QueueingStrategy. * * @param blockingQueue the BlockingQueue to back the returned instance * @param queueingStrategy the QueueingStrategy to use * @param <V> the type of elements held in this collection */ public static <V> StrategicBlockingQueue<V> newStrategicBlockingQueue(BlockingQueue<V> blockingQueue, QueueingStrategy<V> queueingStrategy) { return new StrategicBlockingQueue<V>(blockingQueue, queueingStrategy); } }
/** * Construct a new {@link HeapQueueingStrategy} with the given parameters. * * For example, (0.85, 5000, 10000) translates to when 85% of heap is in * use, start exponentially delaying additional enqueues up to a max of * 5000 ms, garbage collecting after every 10000 dequeues to ensure that * * @param percentOfHeapBeforeFlowControl the percentage of the heap that must be available before the * queue begins to start delaying addition operations * @param maxDelay the maximum amount of time to delay an addition operation in * milliseconds * @param dequeueHint after this many dequeue operations, signal the JVM to run a * garbage collection */ public static <V> QueueingStrategy<V> newHeapQueueingStrategy(double percentOfHeapBeforeFlowControl, long maxDelay, long dequeueHint) { return new HeapQueueingStrategy<V>(percentOfHeapBeforeFlowControl, maxDelay, dequeueHint); } }
@Override public E poll(long timeout, TimeUnit unit) throws InterruptedException { queueingStrategy.onBeforeRemove(); E value = null; try { return value = super.poll(timeout, unit); } finally { queueingStrategy.onAfterRemove(value); } }
@SuppressWarnings("unchecked") @Override public void onError(QSTaskModel task, TaskKit kit, Throwable throwable) { try { kit.worker.onError(kit.factory, kit, throwable); } catch (Throwable anotherThrowable) { LOG.warn("There was an error in worker.onError It will replace the current throwable.", anotherThrowable); throwable = anotherThrowable; } queueingStrategy.onBeforeRemove(); ImmutableMap<String, ImmutableMap<String, String>> exceptionDetails = ImmutableMap.of("exception", ImmutableMap.of( "class", throwable.getClass().getName(), "message", throwable.getMessage(), "stackTrace", ExceptionUtils.getStackTrace(throwable) )); QSLogModel logTick = new QSLogModel(task.taskId, workerIdService.getWorkerId(), task.handler, System.currentTimeMillis(), exceptionDetails); if (LOG.isDebugEnabled()) { LOG.debug("Task erred: {}", logTick, throwable); } else { LOG.info("Task erred: {}", logTick); } logService.log(logTick); if (--task.remainingAttempts > 0) { taskService.resetTask(task); } else { taskService.closeTask(task); } task.finishedHappy = false; }
/** * Return a StrategicBlockingQueue backed by a LinkedBlockingQueue using * the given QueueingStrategy. * * @param queueingStrategy the QueueingStrategy to use * @param <V> the type of elements held in this collection */ public static <V> StrategicBlockingQueue<V> newStrategicLinkedBlockingQueue(QueueingStrategy<V> queueingStrategy) { return new StrategicBlockingQueue<V>(new LinkedBlockingQueue<V>(), queueingStrategy); }
/** * Return a StrategicBlockingQueue backed by an ArrayBlockingQueue of the * given capacity using the given QueueingStrategy. * * @param capacity the capacity of the ArrayBlockingQueue * @param queueingStrategy the QueueingStrategy to use * @param <V> the type of elements held in this collection */ public static <V> StrategicBlockingQueue<V> newStrategicArrayBlockingQueue(int capacity, QueueingStrategy<V> queueingStrategy) { return new StrategicBlockingQueue<V>(new ArrayBlockingQueue<V>(capacity), queueingStrategy); }