package org.cache2k.benchmark.impl2015;
/*
* #%L
* Benchmarks: implementation variants
* %%
* Copyright (C) 2013 - 2017 headissue GmbH, Munich
* %%
* 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.
* #L%
*/
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Provides a shared thread pool used by all caches for background refreshes of expired
* entries. The maximum thread size is the processor count times two.
*
* @author Jens Wilke; created: 2013-06-13
*/
public class CacheRefreshThreadPool {
public static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors() * 2;
private static ThreadPoolExecutor executorForAll;
private static int leasedPoolInstances = 0;
private static MyStatus status;
/**
* Get an instance of the pool. When the consumer is destroyed it must
* call {@link #destroy()} in turn to free resources.
*/
public synchronized static CacheRefreshThreadPool getInstance() {
if (executorForAll == null) {
executorForAll =
new ThreadPoolExecutor(0, THREAD_COUNT,
21, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new MyThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
leasedPoolInstances++;
CacheRefreshThreadPool p = new CacheRefreshThreadPool();
p.executor = executorForAll;
return p;
}
synchronized static void disposeOne() {
leasedPoolInstances--;
if (leasedPoolInstances == 0) {
executorForAll.shutdown();
executorForAll = null;
}
}
private ThreadPoolExecutor executor;
private CacheRefreshThreadPool() {
}
public boolean submit(Runnable r) {
try {
executor.execute(r);
} catch (RejectedExecutionException e) {
return false;
}
return true;
}
public void destroy() {
disposeOne();
executor = null;
}
static class MyThreadFactory implements ThreadFactory {
AtomicInteger count = new AtomicInteger();
@Override
public synchronized Thread newThread(Runnable r) {
Thread t = new Thread(r, "cache2k-refresh-" + count.incrementAndGet());
t.setDaemon(true);
return t;
}
}
static class MyStatus {
public String toString() {
return "CacheRefreshThreadPool(" +
"size=" + executorForAll.getPoolSize() + ", " +
"sizeLargest=" + executorForAll.getLargestPoolSize() + ", " +
"sizeMax=" + executorForAll.getMaximumPoolSize() + ", " +
"taskCount=" + executorForAll.getTaskCount() + ")";
}
}
}