/**
* 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 org.apache.camel.impl;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.camel.ContextTestSupport;
import org.apache.camel.ThreadPoolRejectedPolicy;
import org.apache.camel.spi.ThreadPoolProfile;
import org.apache.camel.util.concurrent.SizedScheduledExecutorService;
/**
* @version
*/
public class DefaultExecutorServiceManagerTest extends ContextTestSupport {
public void testResolveThreadNameDefaultPattern() throws Exception {
String foo = context.getExecutorServiceManager().resolveThreadName("foo");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertTrue(foo.startsWith("Camel (" + context.getName() + ") thread "));
assertTrue(foo.endsWith("foo"));
assertTrue(bar.startsWith("Camel (" + context.getName() + ") thread "));
assertTrue(bar.endsWith("bar"));
}
public void testGetThreadNameCustomPattern() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("##counter# - #name#");
assertEquals("##counter# - #name#", context.getExecutorServiceManager().getThreadNamePattern());
String foo = context.getExecutorServiceManager().resolveThreadName("foo");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertTrue(foo.startsWith("#"));
assertTrue(foo.endsWith(" - foo"));
assertTrue(bar.startsWith("#"));
assertTrue(bar.endsWith(" - bar"));
}
public void testGetThreadNameCustomPatternCamelId() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("##camelId# - ##counter# - #name#");
String foo = context.getExecutorServiceManager().resolveThreadName("foo");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertTrue(foo.startsWith("#" + context.getName() + " - #"));
assertTrue(foo.endsWith(" - foo"));
assertTrue(bar.startsWith("#" + context.getName() + " - #"));
assertTrue(bar.endsWith(" - bar"));
}
public void testGetThreadNameCustomPatternWithDollar() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("Hello - #name#");
String foo = context.getExecutorServiceManager().resolveThreadName("foo$bar");
assertEquals("Hello - foo$bar", foo);
}
public void testGetThreadNameCustomPatternLongName() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("##counter# - #longName#");
String foo = context.getExecutorServiceManager().resolveThreadName("foo?beer=Carlsberg");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertTrue(foo.startsWith("#"));
assertTrue(foo.endsWith(" - foo?beer=Carlsberg"));
assertTrue(bar.startsWith("#"));
assertTrue(bar.endsWith(" - bar"));
}
public void testGetThreadNameCustomPatternWithParameters() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("##counter# - #name#");
String foo = context.getExecutorServiceManager().resolveThreadName("foo?beer=Carlsberg");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertTrue(foo.startsWith("#"));
assertTrue(foo.endsWith(" - foo"));
assertTrue(bar.startsWith("#"));
assertTrue(bar.endsWith(" - bar"));
}
public void testGetThreadNameCustomPatternNoCounter() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("Cool #name#");
String foo = context.getExecutorServiceManager().resolveThreadName("foo");
String bar = context.getExecutorServiceManager().resolveThreadName("bar");
assertNotSame(foo, bar);
assertEquals("Cool foo", foo);
assertEquals("Cool bar", bar);
}
public void testGetThreadNameCustomPatternInvalid() throws Exception {
context.getExecutorServiceManager().setThreadNamePattern("Cool #xxx#");
try {
context.getExecutorServiceManager().resolveThreadName("foo");
fail("Should thrown an exception");
} catch (IllegalArgumentException e) {
assertEquals("Pattern is invalid: Cool #xxx#", e.getMessage());
}
// reset it so we can shutdown properly
context.getExecutorServiceManager().setThreadNamePattern("Camel Thread #counter# - #name#");
}
public void testDefaultThreadPool() throws Exception {
ExecutorService myPool = context.getExecutorServiceManager().newDefaultThreadPool(this, "myPool");
assertEquals(false, myPool.isShutdown());
// should use default settings
ThreadPoolExecutor executor = (ThreadPoolExecutor) myPool;
assertEquals(10, executor.getCorePoolSize());
assertEquals(20, executor.getMaximumPoolSize());
assertEquals(60, executor.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(1000, executor.getQueue().remainingCapacity());
context.stop();
assertEquals(true, myPool.isShutdown());
}
public void testDefaultUnboundedQueueThreadPool() throws Exception {
ThreadPoolProfile custom = new ThreadPoolProfile("custom");
custom.setPoolSize(10);
custom.setMaxPoolSize(30);
custom.setKeepAliveTime(50L);
custom.setMaxQueueSize(Integer.MAX_VALUE);
context.getExecutorServiceManager().setDefaultThreadPoolProfile(custom);
assertEquals(true, custom.isDefaultProfile().booleanValue());
ExecutorService myPool = context.getExecutorServiceManager().newDefaultThreadPool(this, "myPool");
assertEquals(false, myPool.isShutdown());
// should use default settings
ThreadPoolExecutor executor = (ThreadPoolExecutor) myPool;
assertEquals(10, executor.getCorePoolSize());
assertEquals(30, executor.getMaximumPoolSize());
assertEquals(50, executor.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(Integer.MAX_VALUE, executor.getQueue().remainingCapacity());
context.stop();
assertEquals(true, myPool.isShutdown());
}
public void testDefaultNoMaxQueueThreadPool() throws Exception {
ThreadPoolProfile custom = new ThreadPoolProfile("custom");
custom.setPoolSize(10);
custom.setMaxPoolSize(30);
custom.setKeepAliveTime(50L);
custom.setMaxQueueSize(0);
context.getExecutorServiceManager().setDefaultThreadPoolProfile(custom);
assertEquals(true, custom.isDefaultProfile().booleanValue());
ExecutorService myPool = context.getExecutorServiceManager().newDefaultThreadPool(this, "myPool");
assertEquals(false, myPool.isShutdown());
// should use default settings
ThreadPoolExecutor executor = (ThreadPoolExecutor) myPool;
assertEquals(10, executor.getCorePoolSize());
assertEquals(30, executor.getMaximumPoolSize());
assertEquals(50, executor.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(0, executor.getQueue().remainingCapacity());
context.stop();
assertEquals(true, myPool.isShutdown());
}
public void testCustomDefaultThreadPool() throws Exception {
ThreadPoolProfile custom = new ThreadPoolProfile("custom");
custom.setKeepAliveTime(20L);
custom.setMaxPoolSize(40);
custom.setPoolSize(5);
custom.setMaxQueueSize(2000);
context.getExecutorServiceManager().setDefaultThreadPoolProfile(custom);
assertEquals(true, custom.isDefaultProfile().booleanValue());
ExecutorService myPool = context.getExecutorServiceManager().newDefaultThreadPool(this, "myPool");
assertEquals(false, myPool.isShutdown());
// should use default settings
ThreadPoolExecutor executor = (ThreadPoolExecutor) myPool;
assertEquals(5, executor.getCorePoolSize());
assertEquals(40, executor.getMaximumPoolSize());
assertEquals(20, executor.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(2000, executor.getQueue().remainingCapacity());
context.stop();
assertEquals(true, myPool.isShutdown());
}
public void testGetThreadPoolProfile() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setKeepAliveTime(20L);
foo.setMaxPoolSize(40);
foo.setPoolSize(5);
foo.setMaxQueueSize(2000);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
assertSame(foo, context.getExecutorServiceManager().getThreadPoolProfile("foo"));
}
public void testTwoGetThreadPoolProfile() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setKeepAliveTime(20L);
foo.setMaxPoolSize(40);
foo.setPoolSize(5);
foo.setMaxQueueSize(2000);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
ThreadPoolProfile bar = new ThreadPoolProfile("bar");
bar.setKeepAliveTime(40L);
bar.setMaxPoolSize(5);
bar.setPoolSize(1);
bar.setMaxQueueSize(100);
context.getExecutorServiceManager().registerThreadPoolProfile(bar);
assertSame(foo, context.getExecutorServiceManager().getThreadPoolProfile("foo"));
assertSame(bar, context.getExecutorServiceManager().getThreadPoolProfile("bar"));
assertNotSame(foo, bar);
assertFalse(context.getExecutorServiceManager().getThreadPoolProfile("foo").isDefaultProfile());
assertFalse(context.getExecutorServiceManager().getThreadPoolProfile("bar").isDefaultProfile());
}
public void testGetThreadPoolProfileInheritDefaultValues() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setMaxPoolSize(40);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
assertSame(foo, context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ExecutorService executor = context.getExecutorServiceManager().newThreadPool(this, "MyPool", "foo");
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, executor);
assertEquals(40, tp.getMaximumPoolSize());
// should inherit the default values
assertEquals(10, tp.getCorePoolSize());
assertEquals(60, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals("CallerRuns", tp.getRejectedExecutionHandler().toString());
}
public void testGetThreadPoolProfileInheritCustomDefaultValues() throws Exception {
ThreadPoolProfile newDefault = new ThreadPoolProfile("newDefault");
newDefault.setKeepAliveTime(30L);
newDefault.setMaxPoolSize(50);
newDefault.setPoolSize(5);
newDefault.setMaxQueueSize(2000);
newDefault.setRejectedPolicy(ThreadPoolRejectedPolicy.Abort);
context.getExecutorServiceManager().setDefaultThreadPoolProfile(newDefault);
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setMaxPoolSize(25);
foo.setPoolSize(1);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
assertSame(foo, context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ExecutorService executor = context.getExecutorServiceManager().newThreadPool(this, "MyPool", "foo");
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, executor);
assertEquals(25, tp.getMaximumPoolSize());
// should inherit the default values
assertEquals(1, tp.getCorePoolSize());
assertEquals(30, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals("Abort", tp.getRejectedExecutionHandler().toString());
}
public void testGetThreadPoolProfileInheritCustomDefaultValues2() throws Exception {
ThreadPoolProfile newDefault = new ThreadPoolProfile("newDefault");
// just change the max pool as the default profile should then inherit the old default profile
newDefault.setMaxPoolSize(50);
context.getExecutorServiceManager().setDefaultThreadPoolProfile(newDefault);
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setPoolSize(1);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
assertSame(foo, context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ExecutorService executor = context.getExecutorServiceManager().newThreadPool(this, "MyPool", "foo");
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, executor);
assertEquals(1, tp.getCorePoolSize());
// should inherit the default values
assertEquals(50, tp.getMaximumPoolSize());
assertEquals(60, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals("CallerRuns", tp.getRejectedExecutionHandler().toString());
}
public void testNewThreadPoolProfile() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setKeepAliveTime(20L);
foo.setMaxPoolSize(40);
foo.setPoolSize(5);
foo.setMaxQueueSize(2000);
ExecutorService pool = context.getExecutorServiceManager().newThreadPool(this, "Cool", foo);
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
assertEquals(20, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(40, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewThreadPoolProfileById() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setKeepAliveTime(20L);
foo.setMaxPoolSize(40);
foo.setPoolSize(5);
foo.setMaxQueueSize(2000);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
ExecutorService pool = context.getExecutorServiceManager().newThreadPool(this, "Cool", "foo");
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
assertEquals(20, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(40, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewThreadPoolMinMax() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newThreadPool(this, "Cool", 5, 10);
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
assertEquals(60, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(10, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewFixedThreadPool() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newFixedThreadPool(this, "Cool", 5);
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
// a fixed dont use keep alive
assertEquals("keepAliveTime", 0, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals("maximumPoolSize", 5, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewSingleThreadExecutor() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newSingleThreadExecutor(this, "Cool");
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
// a single dont use keep alive
assertEquals("keepAliveTime", 0, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals("maximumPoolSize", 1, tp.getMaximumPoolSize());
assertEquals(1, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewScheduledThreadPool() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newScheduledThreadPool(this, "Cool", 5);
assertNotNull(pool);
SizedScheduledExecutorService tp = assertIsInstanceOf(SizedScheduledExecutorService.class, pool);
// a scheduled dont use keep alive
assertEquals(0, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(Integer.MAX_VALUE, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewSingleThreadScheduledExecutor() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newSingleThreadScheduledExecutor(this, "Cool");
assertNotNull(pool);
SizedScheduledExecutorService tp = assertIsInstanceOf(SizedScheduledExecutorService.class, pool);
// a scheduled dont use keep alive
assertEquals(0, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(Integer.MAX_VALUE, tp.getMaximumPoolSize());
assertEquals(1, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewCachedThreadPool() throws Exception {
ExecutorService pool = context.getExecutorServiceManager().newCachedThreadPool(this, "Cool");
assertNotNull(pool);
ThreadPoolExecutor tp = assertIsInstanceOf(ThreadPoolExecutor.class, pool);
assertEquals(60, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(Integer.MAX_VALUE, tp.getMaximumPoolSize());
assertEquals(0, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewScheduledThreadPoolProfileById() throws Exception {
assertNull(context.getExecutorServiceManager().getThreadPoolProfile("foo"));
ThreadPoolProfile foo = new ThreadPoolProfile("foo");
foo.setKeepAliveTime(20L);
foo.setMaxPoolSize(40);
foo.setPoolSize(5);
foo.setMaxQueueSize(2000);
context.getExecutorServiceManager().registerThreadPoolProfile(foo);
ExecutorService pool = context.getExecutorServiceManager().newScheduledThreadPool(this, "Cool", "foo");
assertNotNull(pool);
SizedScheduledExecutorService tp = assertIsInstanceOf(SizedScheduledExecutorService.class, pool);
// a scheduled dont use keep alive
assertEquals(0, tp.getKeepAliveTime(TimeUnit.SECONDS));
assertEquals(Integer.MAX_VALUE, tp.getMaximumPoolSize());
assertEquals(5, tp.getCorePoolSize());
assertFalse(tp.isShutdown());
context.stop();
assertTrue(tp.isShutdown());
}
public void testNewThread() throws Exception {
Thread thread = context.getExecutorServiceManager().newThread("Cool", new Runnable() {
@Override
public void run() {
// noop
}
});
assertNotNull(thread);
assertTrue(thread.isDaemon());
assertTrue(thread.getName().contains("Cool"));
}
// this is a manual test, by looking at the logs
public void xxxTestLongShutdownOfThreadPool() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
ExecutorService pool = context.getExecutorServiceManager().newSingleThreadExecutor(this, "Cool");
pool.execute(new Runnable() {
@Override
public void run() {
log.info("Starting thread");
// this should take a long time to shutdown
try {
latch.await(42, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// ignore
}
log.info("Existing thread");
}
});
// sleep a bit before shutting down
Thread.sleep(3000);
context.getExecutorServiceManager().shutdown(pool);
assertTrue(pool.isShutdown());
assertTrue(pool.isTerminated());
}
}