gov.nist.javax.sip.ThreadAffinityExecutor Maven / Gradle / Ivy
package gov.nist.javax.sip;
import gov.nist.core.CommonLogger;
import gov.nist.core.NamingThreadFactory;
import gov.nist.core.StackLogger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadAffinityExecutor implements ScheduledExecutorService {
private static StackLogger logger = CommonLogger.getLogger(ThreadAffinityExecutor.class);
private final List executors;
private final AtomicInteger nextThread = new AtomicInteger(0);
public ThreadAffinityExecutor(int corePoolSize) {
executors = new ArrayList();
NamingThreadFactory namingThreadFactory = new NamingThreadFactory("AffinityJAIN");
for (int i = 0; i < corePoolSize; i++) {
executors.add(new MDCScheduledTHExecutor(1, namingThreadFactory));
}
schedulePurgeTaskIfNeeded();
}
private synchronized int retrieveNextThread() {
int nThread;
nThread = nextThread.incrementAndGet();
if (nThread >= executors.size()) {
nThread = 0;
nextThread.set(0);
}
if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
logger.logDebug("Next thread id=" + nThread);
}
return nThread;
}
private int calculateAffinityThread(Runnable runnable) {
int affThreadIndex = 0;
if (runnable instanceof ThreadAffinityIdentifier) {
ThreadAffinityIdentifier tTask = (ThreadAffinityIdentifier) runnable;
Object tHash = tTask.getThreadHash();
if (tHash != null) {
affThreadIndex = Math.abs(tHash.hashCode() % executors.size());
if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
logger.logDebug("Runnable assigned to thread (" + tHash + "," + affThreadIndex + ")");
}
} else {
affThreadIndex = retrieveNextThread();
}
} else {
affThreadIndex = retrieveNextThread();
}
return affThreadIndex;
}
@Override
public ScheduledFuture> schedule(Runnable command, long delay, TimeUnit unit) {
int affThread = calculateAffinityThread(command);
return executors.get(affThread).schedule(command, delay, unit);
}
@Override
public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public ScheduledFuture> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
int affThread = calculateAffinityThread(command);
return executors.get(affThread).scheduleAtFixedRate(command, initialDelay, period, unit);
}
@Override
public ScheduledFuture> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
int affThread = calculateAffinityThread(command);
return executors.get(affThread).scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
@Override
public void shutdown() {
for (ScheduledExecutorService serv : executors) {
serv.shutdown();
}
}
@Override
public List shutdownNow() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean isShutdown() {
return executors.get(0).isShutdown();
}
@Override
public boolean isTerminated() {
return executors.get(0).isTerminated();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return executors.get(0).awaitTermination(timeout, unit);
}
@Override
public Future submit(Callable task) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Future submit(Runnable task, T result) {
int affThread = calculateAffinityThread(task);
return executors.get(affThread).submit(task, result);
}
@Override
public Future> submit(Runnable task) {
int affThread = calculateAffinityThread(task);
return executors.get(affThread).submit(task);
}
@Override
public List> invokeAll(Collection extends Callable> tasks) throws InterruptedException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public List> invokeAll(Collection extends Callable> tasks, long timeout, TimeUnit unit) throws InterruptedException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public T invokeAny(Collection extends Callable> tasks) throws InterruptedException, ExecutionException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public T invokeAny(Collection extends Callable> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void execute(Runnable command) {
int affThread = calculateAffinityThread(command);
executors.get(affThread).execute(command);
}
private void schedulePurgeTaskIfNeeded() {
//TODO
/*int purgePeriod = Integer.parseInt(sipStackImpl.getConfigurationProperties().getProperty("gov.nist.javax.sip.timers.SCHEDULED_EXECUTOR_PURGE_DELAY", "1"));
if (purgePeriod > 0) {
Runnable r = new Runnable() {
public void run() {
try {
if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
logger.logDebug("Purging canceled timer tasks...");
}
for (MDCScheduledTHExecutor serv : executors) {
serv.purge();
}
if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) {
logger.logDebug("Purging canceled timer tasks completed.");
}
} catch (Exception e) {
logger.logError("failed to execute purge", e);
}
}
};
scheduleWithFixedDelay(r, purgePeriod, purgePeriod, TimeUnit.MINUTES);
}*/
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy