001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.messaging.simp.config; 018 019import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 020import org.springframework.util.Assert; 021 022/** 023 * A registration class for customizing the properties of {@link ThreadPoolTaskExecutor}. 024 * 025 * @author Rossen Stoyanchev 026 * @author Juergen Hoeller 027 * @since 4.0 028 */ 029public class TaskExecutorRegistration { 030 031 private final ThreadPoolTaskExecutor taskExecutor; 032 033 private Integer corePoolSize; 034 035 private Integer maxPoolSize; 036 037 private Integer keepAliveSeconds; 038 039 private Integer queueCapacity; 040 041 042 /** 043 * Create a new {@code TaskExecutorRegistration} for a default 044 * {@link ThreadPoolTaskExecutor}. 045 */ 046 public TaskExecutorRegistration() { 047 this.taskExecutor = new ThreadPoolTaskExecutor(); 048 this.taskExecutor.setCorePoolSize(Runtime.getRuntime().availableProcessors() * 2); 049 this.taskExecutor.setAllowCoreThreadTimeOut(true); 050 } 051 052 /** 053 * Create a new {@code TaskExecutorRegistration} for a given 054 * {@link ThreadPoolTaskExecutor}. 055 * @param taskExecutor the executor to use 056 */ 057 public TaskExecutorRegistration(ThreadPoolTaskExecutor taskExecutor) { 058 Assert.notNull(taskExecutor, "ThreadPoolTaskExecutor must not be null"); 059 this.taskExecutor = taskExecutor; 060 } 061 062 063 /** 064 * Set the core pool size of the ThreadPoolExecutor. 065 * <p><strong>NOTE:</strong> The core pool size is effectively the max pool size 066 * when an unbounded {@link #queueCapacity(int) queueCapacity} is configured 067 * (the default). This is essentially the "Unbounded queues" strategy as explained 068 * in {@link java.util.concurrent.ThreadPoolExecutor ThreadPoolExecutor}. When 069 * this strategy is used, the {@link #maxPoolSize(int) maxPoolSize} is ignored. 070 * <p>By default this is set to twice the value of 071 * {@link Runtime#availableProcessors()}. In an application where tasks do not 072 * block frequently, the number should be closer to or equal to the number of 073 * available CPUs/cores. 074 */ 075 public TaskExecutorRegistration corePoolSize(int corePoolSize) { 076 this.corePoolSize = corePoolSize; 077 return this; 078 } 079 080 /** 081 * Set the max pool size of the ThreadPoolExecutor. 082 * <p><strong>NOTE:</strong> When an unbounded 083 * {@link #queueCapacity(int) queueCapacity} is configured (the default), the 084 * max pool size is effectively ignored. See the "Unbounded queues" strategy 085 * in {@link java.util.concurrent.ThreadPoolExecutor ThreadPoolExecutor} for 086 * more details. 087 * <p>By default this is set to {@code Integer.MAX_VALUE}. 088 */ 089 public TaskExecutorRegistration maxPoolSize(int maxPoolSize) { 090 this.maxPoolSize = maxPoolSize; 091 return this; 092 } 093 094 /** 095 * Set the time limit for which threads may remain idle before being terminated. 096 * If there are more than the core number of threads currently in the pool, 097 * after waiting this amount of time without processing a task, excess threads 098 * will be terminated. This overrides any value set in the constructor. 099 * <p>By default this is set to 60. 100 */ 101 public TaskExecutorRegistration keepAliveSeconds(int keepAliveSeconds) { 102 this.keepAliveSeconds = keepAliveSeconds; 103 return this; 104 } 105 106 /** 107 * Set the queue capacity for the ThreadPoolExecutor. 108 * <p><strong>NOTE:</strong> when an unbounded {@code queueCapacity} is configured 109 * (the default), the core pool size is effectively the max pool size. This is 110 * essentially the "Unbounded queues" strategy as explained in 111 * {@link java.util.concurrent.ThreadPoolExecutor ThreadPoolExecutor}. When 112 * this strategy is used, the {@link #maxPoolSize(int) maxPoolSize} is ignored. 113 * <p>By default this is set to {@code Integer.MAX_VALUE}. 114 */ 115 public TaskExecutorRegistration queueCapacity(int queueCapacity) { 116 this.queueCapacity = queueCapacity; 117 return this; 118 } 119 120 121 protected ThreadPoolTaskExecutor getTaskExecutor() { 122 if (this.corePoolSize != null) { 123 this.taskExecutor.setCorePoolSize(this.corePoolSize); 124 } 125 if (this.maxPoolSize != null) { 126 this.taskExecutor.setMaxPoolSize(this.maxPoolSize); 127 } 128 if (this.keepAliveSeconds != null) { 129 this.taskExecutor.setKeepAliveSeconds(this.keepAliveSeconds); 130 } 131 if (this.queueCapacity != null) { 132 this.taskExecutor.setQueueCapacity(this.queueCapacity); 133 } 134 return this.taskExecutor; 135 } 136 137}