/*
* Copyright 2014-2016 CyberVision, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaaproject.kaa.client.context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class FlexibleExecutorContext extends AbstractExecutorContext implements ExecutorContext {
private static final Logger LOG = LoggerFactory.getLogger(FlexibleExecutorContext.class);
public static final int DEFAULT_MIN_THREADS = 0;
public static final int DEFAULT_MAX_THREADS = Integer.MAX_VALUE;
public static final int DEFAULT_MAX_THREAD_IDLE_MILLISECONDS = 100;
private final int maxLifeCycleThreads;
private final int maxApiThreads;
private final int maxCallbackThreads;
private final int minScheduledThreads;
private final int maxLifeCycleThreadsIdleMilliseconds;
private final int maxApiThreadsIdleMilliseconds;
private final int maxCallbackThreadsIdleMilliseconds;
private ExecutorService lifeCycleExecutor;
private ExecutorService apiExecutor;
private ExecutorService callbackExecutor;
private ScheduledExecutorService scheduledExecutor;
public FlexibleExecutorContext() {
this(DEFAULT_MAX_THREADS, DEFAULT_MAX_THREADS, DEFAULT_MAX_THREADS, DEFAULT_MIN_THREADS);
}
/**
* All-args constructor.
*/
public FlexibleExecutorContext(int maxLifeCycleThreads, int maxApiThreads,
int maxCallbackThreads, int minScheduledThreads) {
this.maxLifeCycleThreads = maxLifeCycleThreads;
this.maxApiThreads = maxApiThreads;
this.maxCallbackThreads = maxCallbackThreads;
this.minScheduledThreads = minScheduledThreads;
maxLifeCycleThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
maxCallbackThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
maxApiThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
}
/**
* Constructor for Builder pattern.
*/
private FlexibleExecutorContext(FlexibleExecutorContextBuilder builder) {
maxLifeCycleThreads = builder.getMaxLifeCycleThreads();
maxApiThreads = builder.getMaxApiThreads();
maxCallbackThreads = builder.getMaxCallbackThreads();
minScheduledThreads = builder.getMinScheduledThreads();
maxLifeCycleThreadsIdleMilliseconds = builder.getMaxLifeCycleThreadsIdleMilliseconds();
maxCallbackThreadsIdleMilliseconds = builder.getMaxCallbackThreadsIdleMilliseconds();
maxApiThreadsIdleMilliseconds = builder.getMaxApiThreadsIdleMilliseconds();
}
@Override
public void init() {
LOG.debug("Creating executor services");
lifeCycleExecutor = createExecutor(maxLifeCycleThreads, maxLifeCycleThreadsIdleMilliseconds);
apiExecutor = createExecutor(maxApiThreads, maxApiThreadsIdleMilliseconds);
callbackExecutor = createExecutor(maxCallbackThreads, maxCallbackThreadsIdleMilliseconds);
scheduledExecutor = createScheduledExecutor(minScheduledThreads);
LOG.debug("Creation of executor services is finished");
}
@Override
public void stop() {
shutdownExecutor(lifeCycleExecutor);
shutdownExecutor(apiExecutor);
shutdownExecutor(callbackExecutor);
shutdownExecutor(scheduledExecutor);
}
@Override
public ExecutorService getLifeCycleExecutor() {
return lifeCycleExecutor;
}
@Override
public ExecutorService getApiExecutor() {
return apiExecutor;
}
@Override
public ExecutorService getCallbackExecutor() {
return callbackExecutor;
}
@Override
public ScheduledExecutorService getScheduledExecutor() {
return scheduledExecutor;
}
private ExecutorService createExecutor(int maxThreads, int maxThreadsIdleMilliseconds) {
return new ThreadPoolExecutor(DEFAULT_MIN_THREADS, maxThreads,
maxThreadsIdleMilliseconds, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
}
private ScheduledExecutorService createScheduledExecutor(int minThreads) {
return Executors.newScheduledThreadPool(minThreads);
}
public static class FlexibleExecutorContextBuilder {
private int maxLifeCycleThreads = DEFAULT_MAX_THREADS;
private int maxApiThreads = DEFAULT_MAX_THREADS;
private int maxCallbackThreads = DEFAULT_MAX_THREADS;
private int minScheduledThreads = DEFAULT_MIN_THREADS;
private int maxLifeCycleThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
private int maxApiThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
private int maxCallbackThreadsIdleMilliseconds = DEFAULT_MAX_THREAD_IDLE_MILLISECONDS;
public FlexibleExecutorContextBuilder setMaxLifeCycleThreads(int maxLifeCycleThreads) {
this.maxLifeCycleThreads = maxLifeCycleThreads;
return this;
}
public FlexibleExecutorContextBuilder setMaxApiThreads(int maxApiThreads) {
this.maxApiThreads = maxApiThreads;
return this;
}
public FlexibleExecutorContextBuilder setMaxCallbackThreads(int maxCallbackThreads) {
this.maxCallbackThreads = maxCallbackThreads;
return this;
}
public FlexibleExecutorContextBuilder setMinScheduledThreads(int minScheduledThreads) {
this.minScheduledThreads = minScheduledThreads;
return this;
}
public FlexibleExecutorContextBuilder setMaxLifeCycleThreadsIdleMilliseconds(int maxLifeCycleThreadsIdleMilliseconds) {
this.maxLifeCycleThreadsIdleMilliseconds = maxLifeCycleThreadsIdleMilliseconds;
return this;
}
public FlexibleExecutorContextBuilder setMaxApiThreadsIdleMilliseconds(int maxApiThreadsIdleMilliseconds) {
this.maxApiThreadsIdleMilliseconds = maxApiThreadsIdleMilliseconds;
return this;
}
public FlexibleExecutorContextBuilder setMaxCallbackThreadsIdleMilliseconds(int maxCallbackThreadsIdleMilliseconds) {
this.maxCallbackThreadsIdleMilliseconds = maxCallbackThreadsIdleMilliseconds;
return this;
}
/**
* Set threads amount and appropriate idle time for life cycle threads.
*
* @param lifeCycleThreadCount threads amount
* @param maxLifeCycleThreadsIdleMilliseconds idle time (milliseconds)
* @return builder
*/
public FlexibleExecutorContextBuilder setLifeCycleThreadCountAndIdleMilliseconds(
int lifeCycleThreadCount, int maxLifeCycleThreadsIdleMilliseconds) {
this.maxLifeCycleThreads = lifeCycleThreadCount;
this.maxLifeCycleThreadsIdleMilliseconds = maxLifeCycleThreadsIdleMilliseconds;
return this;
}
/**
* Set threads amount and appropriate idle time for api`s threads.
*
* @param apiThreadCount threads amount
* @param maxApiThreadsIdleMilliseconds idle time (milliseconds)
* @return builder
*/
public FlexibleExecutorContextBuilder setApiThreadCountAndIdleMilliseconds(
int apiThreadCount, int maxApiThreadsIdleMilliseconds) {
this.maxApiThreads = apiThreadCount;
this.maxApiThreadsIdleMilliseconds = maxApiThreadsIdleMilliseconds;
return this;
}
/**
* Set threads amount and appropriate idle time for callback`s threads.
*
* @param callbackThreadCount threads amount
* @param maxCallbackThreadsIdleMilliseconds idle time (milliseconds)
* @return builder
*/
public FlexibleExecutorContextBuilder setCallbackThreadCountAndIdleMilliseconds(
int callbackThreadCount, int maxCallbackThreadsIdleMilliseconds) {
this.maxCallbackThreads = callbackThreadCount;
this.maxCallbackThreadsIdleMilliseconds = maxCallbackThreadsIdleMilliseconds;
return this;
}
public FlexibleExecutorContext build() {
return new FlexibleExecutorContext(this);
}
int getMaxLifeCycleThreads() {
return maxLifeCycleThreads;
}
int getMaxApiThreads() {
return maxApiThreads;
}
int getMaxCallbackThreads() {
return maxCallbackThreads;
}
int getMinScheduledThreads() {
return minScheduledThreads;
}
int getMaxLifeCycleThreadsIdleMilliseconds() {
return maxLifeCycleThreadsIdleMilliseconds;
}
int getMaxApiThreadsIdleMilliseconds() {
return maxApiThreadsIdleMilliseconds;
}
int getMaxCallbackThreadsIdleMilliseconds() {
return maxCallbackThreadsIdleMilliseconds;
}
}
}