All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.therore.concurrent.SelfTuningExecutorService Maven / Gradle / Ivy

Go to download

Therore Concurrency Libraries are an expanded set of services and types supporting advanced concurrent programming in Java.

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 net.therore.concurrent;

import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

import net.therore.concurrent.SampleContainer.ExecutionState;

/**
 * @author [email protected]
 */
public class SelfTuningExecutorService extends AbstractExecutorService implements ExecutorService, SelfTuningExecutorServiceMBean {
	static public final long POLL_MSECS = 5000;
	static public final int DEFAULT_POOLSIZE = 1;
	
	private final ReentrantLock mainLock = new ReentrantLock();

    static final int RUNNING    = 0;
    static final int SHUTDOWN   = 1;
    static final int STOP       = 2;
    static final int TERMINATED = 3;

	private final String name;
	private final SelfTuningExecutors executors;
	private final ThreadPoolExecutor coreExecutorService;
	private final SampleContainer sampleContainer;
	private final ArrayBlockingQueue workQueue;
	private final ParameterOptimizer optimizer;
	private final AtomicInteger activeCount;
	private final AtomicInteger totalExecutions;
	private final int queueSize;
	private final int initPoolSize;
	private final int corePoolSize;
	private final int maximumPoolSize;
	private final int priority;
	private volatile int poolSize = DEFAULT_POOLSIZE;

	
	public SelfTuningExecutorService(SelfTuningExecutors executors, ThreadPoolExecutor coreExecutorService, String name
			, int corePoolSize, int initPoolSize, int maximumPoolSize, int priority, int queueSize) {
		this.name = name==null ? String.valueOf(System.identityHashCode(this)) : name;
		this.executors = executors;
		this.coreExecutorService = coreExecutorService;
		this.sampleContainer = new SampleContainer(initPoolSize);
		this.queueSize = queueSize;
		this.workQueue = new ArrayBlockingQueue(queueSize, true);
		this.activeCount = new AtomicInteger(0);
		this.totalExecutions = new AtomicInteger(0);
		this.initPoolSize = initPoolSize;
		this.poolSize = initPoolSize;
		this.corePoolSize = corePoolSize;
		this.maximumPoolSize = maximumPoolSize;
		this.priority = priority;
		this.optimizer = new ParameterOptimizer(corePoolSize, maximumPoolSize, priority) {
			public int getTotalPriority() {
				return SelfTuningExecutorService.this.executors.getTotalPriority();
			}
			public int getTotalValue() {
				return SelfTuningExecutorService.this.executors.getPoolSize();
			}
		};
	}

	@Override
	public String getName() {
		return name;
	}
	
	@Override
	public int getQueueSize() {
		return queueSize;
	}
	
	@Override
	public int getInitPoolSize() {
		return initPoolSize;
	}

	@Override
	public int getCorePoolSize() {
		return corePoolSize;
	}

	@Override
	public int getMaximumPoolSize() {
		return maximumPoolSize;
	}

	@Override
	public int getPriority() {
		return priority;
	}

	@Override
	public int getPoolSize() {
		return poolSize;
	}
	
	@Override
	public double getThroughput() {
		return sampleContainer.getThroughput();
	}

	@Override
	public int getActiveCount() {
		return activeCount.get();
	}
	
	@Override
	public int getTotalExecutions() {
		return totalExecutions.get();
	}
		
	public int getRunState() {
		if (!coreExecutorService.isShutdown())
			return RUNNING;
		else if (coreExecutorService.isTerminated())
			return TERMINATED;
		else
			return SHUTDOWN;
		
		// NO STOP STATE
	}
	
	@Override
	public void shutdown() {
		coreExecutorService.shutdown();
	}

	@Override
	public List shutdownNow() {
		return coreExecutorService.shutdownNow();
	}

	@Override
	public boolean isShutdown() {
		return coreExecutorService.isShutdown();
	}
	
	@Override
	public boolean isTerminated() {
		return coreExecutorService.isTerminated();
	}
	
	@Override
	public boolean isTerminating() {
		return coreExecutorService.isTerminating();
	}

	@Override
	public boolean awaitTermination(long timeout, TimeUnit unit)
			throws InterruptedException {
		return coreExecutorService.awaitTermination(timeout, unit);
	}
	
	@Override
	public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int runState = getRunState();
        try {
        	while (!addIfUnderCorePoolSize(command)) {
        		if (runState == RUNNING && workQueue.offer(command, POLL_MSECS, TimeUnit.MILLISECONDS)) {
        			if (runState != RUNNING || poolSize == 0)
        				ensureQueuedTaskHandled(command);
        			break;
        		}
        		if (runState != RUNNING)
        			break;
        	}
        } catch (InterruptedException e) {
        	reject(command);
        }
    }
	
	void reject(Runnable command) {
        coreExecutorService.getRejectedExecutionHandler().rejectedExecution(command, coreExecutorService);
    }

    private void addThread(Runnable firstTask) {
    	FlowControlWrapper w = new FlowControlWrapper(firstTask);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        	activeCount.incrementAndGet();
        } finally {
            mainLock.unlock();
        }
    	coreExecutorService.execute(w);
    }	

    private boolean addIfUnderCorePoolSize(Runnable firstTask) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int runState = getRunState();
            if (activeCount.get() < poolSize && runState == RUNNING) {
            	addThread(firstTask);
                return true;
            } else
            	return false;
        } finally {
            mainLock.unlock();
        }
    }	
    
    private void ensureQueuedTaskHandled(Runnable command) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        boolean reject = false;
        try {
            int state = getRunState();
            if (state != RUNNING && workQueue.remove(command))
                reject = true;
            else if (state < STOP && activeCount.get() < poolSize &&
                    !workQueue.isEmpty())
            	addThread(null);
        } finally {
            mainLock.unlock();
        }
        if (reject)
            reject(command);
    }
    

    protected Runnable getTask() {
        for (;;) {
            int state = getRunState();
            Runnable r;
            if (state == SHUTDOWN)  // Help drain queue
                r = workQueue.poll();
            else if (activeCount.get() <= poolSize)
                r = workQueue.poll();
            else
                r = null;

            return r;
        }
    }    
    
    void workerDone(FlowControlWrapper w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (activeCount.decrementAndGet() == 0)
                tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }
    
    private void tryTerminate() {
        if (activeCount.get() == 0) {
            int state = getRunState();
            if (state < STOP && !workQueue.isEmpty()) {
                state = RUNNING; // disable termination check below
                addThread(null);
            }
        }
    }
    
	public class FlowControlWrapper implements Runnable {

		private Runnable firstTask;

		public FlowControlWrapper(Runnable firstTask) {
			this.firstTask = firstTask;
		}
		
        /**
         * Main run loop
         */
		@Override
        public void run() {
            try {
                Runnable task = firstTask;
                firstTask = null;
                while (task != null || (task = getTask()) != null) {
                	// annotate start execution
                	sampleContainer.annotationExecution(System.currentTimeMillis(), optimizer, ExecutionState.STARTED);
                	totalExecutions.incrementAndGet();
                	task.run();
                    task = null;

                	// annotate end execution
        			int tmpPoolSize = sampleContainer.annotationExecution(System.currentTimeMillis(), optimizer, ExecutionState.TERMINATED);
        	        final ReentrantLock mainLock = SelfTuningExecutorService.this.mainLock;
        	        mainLock.lock();
        	        try {
       	        		poolSize = tmpPoolSize;
        	        	int count = activeCount.get();
        	        	if (count > tmpPoolSize)
        	        		break;
        	        	else if (count < tmpPoolSize)
        	        		addThread(null);
        	        } finally {
        	        	mainLock.unlock();
        	        }
                }
            } finally {
                workerDone(this);
            }
        }

		
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy