1 58 59 package org.opencms.scheduler; 60 61 import org.opencms.main.CmsLog; 62 63 import org.apache.commons.logging.Log; 64 65 import org.quartz.SchedulerConfigException; 66 import org.quartz.spi.ThreadPool; 67 68 79 public class CmsSchedulerThreadPool implements ThreadPool { 80 81 82 private static final Log LOG = CmsLog.getLog(CmsSchedulerThreadPool.class); 83 84 private int m_currentThreadCount; 85 86 private boolean m_inheritGroup; 87 88 private boolean m_inheritLoader; 89 90 private int m_initialThreadCount; 91 92 private boolean m_isShutdown; 93 94 private boolean m_makeThreadsDaemons; 95 96 private int m_maxThreadCount; 97 98 private Runnable m_nextRunnable; 99 100 private Object m_nextRunnableLock; 101 102 private ThreadGroup m_threadGroup; 103 104 private String m_threadNamePrefix; 105 106 private int m_threadPriority; 107 108 private CmsSchedulerThread[] m_workers; 109 110 118 public CmsSchedulerThreadPool() { 119 120 this(0, 10, Thread.NORM_PRIORITY); 121 } 122 123 140 public CmsSchedulerThreadPool(int initialThreadCount, int maxThreadCount, int threadPriority) { 141 142 m_inheritGroup = true; 143 m_inheritLoader = true; 144 m_nextRunnableLock = new Object (); 145 m_threadNamePrefix = "OpenCms: Scheduler Thread "; 146 m_makeThreadsDaemons = true; 147 m_initialThreadCount = initialThreadCount; 148 m_currentThreadCount = 0; 149 m_maxThreadCount = maxThreadCount; 150 m_threadPriority = threadPriority; 151 } 152 153 156 public int getPoolSize() { 157 158 return m_currentThreadCount; 159 } 160 161 166 public int getThreadPriority() { 167 168 return m_threadPriority; 169 } 170 171 174 public void initialize() throws SchedulerConfigException { 175 176 if (m_maxThreadCount <= 0 || m_maxThreadCount > 200) { 177 throw new SchedulerConfigException(Messages.get().getBundle().key(Messages.ERR_MAX_THREAD_COUNT_BOUNDS_0)); 178 } 179 if (m_initialThreadCount < 0 || m_initialThreadCount > m_maxThreadCount) { 180 throw new SchedulerConfigException(Messages.get().getBundle().key(Messages.ERR_INIT_THREAD_COUNT_BOUNDS_0)); 181 } 182 if (m_threadPriority <= 0 || m_threadPriority > 9) { 183 throw new SchedulerConfigException(Messages.get().getBundle().key(Messages.ERR_SCHEDULER_PRIORITY_BOUNDS_0)); 184 } 185 186 if (m_inheritGroup) { 187 m_threadGroup = Thread.currentThread().getThreadGroup(); 188 } else { 189 m_threadGroup = Thread.currentThread().getThreadGroup(); 191 ThreadGroup parent = m_threadGroup; 192 while (!parent.getName().equals("main")) { 193 m_threadGroup = parent; 194 parent = m_threadGroup.getParent(); 195 } 196 m_threadGroup = new ThreadGroup (parent, this.getClass().getName()); 197 } 198 199 if (m_inheritLoader) { 200 LOG.debug(Messages.get().getBundle().key( 201 Messages.LOG_USING_THREAD_CLASSLOADER_1, 202 Thread.currentThread().getName())); 203 } 204 205 m_workers = new CmsSchedulerThread[m_maxThreadCount]; 207 for (int i = 0; i < m_initialThreadCount; ++i) { 208 growThreadPool(); 209 } 210 } 211 212 223 public boolean runInThread(Runnable runnable) { 224 225 if (runnable == null) { 226 return false; 227 } 228 229 if (m_isShutdown) { 230 LOG.debug(Messages.get().getBundle().key(Messages.LOG_THREAD_POOL_UNAVAILABLE_0)); 231 return false; 232 } 233 234 if ((m_currentThreadCount == 0) || (m_nextRunnable != null)) { 235 growThreadPool(); 237 } 238 239 synchronized (m_nextRunnableLock) { 240 241 while ((m_nextRunnable != null) && !m_isShutdown) { 244 try { 245 m_nextRunnableLock.wait(1000); 246 } catch (InterruptedException e) { 247 } 249 } 250 251 if (!m_isShutdown) { 254 m_nextRunnable = runnable; 255 m_nextRunnableLock.notifyAll(); 256 } 257 } 258 259 if (m_isShutdown) { 264 new CmsSchedulerThread( 265 this, 266 m_threadGroup, 267 m_threadNamePrefix + "(final)", 268 m_threadPriority, 269 false, 270 runnable); 271 } 272 273 return true; 274 } 275 276 281 public void shutdown() { 282 283 shutdown(true); 284 } 285 286 291 public void shutdown(boolean waitForJobsToComplete) { 292 293 m_isShutdown = true; 294 295 for (int i = 0; i < m_currentThreadCount; i++) { 297 if (m_workers[i] != null) { 298 m_workers[i].shutdown(); 299 } 300 } 301 302 synchronized (m_nextRunnableLock) { 306 m_nextRunnableLock.notifyAll(); 307 } 308 309 if (waitForJobsToComplete) { 310 int alive = m_currentThreadCount; 312 while (alive > 0) { 313 alive = 0; 314 for (int i = 0; i < m_currentThreadCount; i++) { 315 if (m_workers[i].isAlive()) { 316 try { 317 if (LOG.isDebugEnabled()) { 318 LOG.debug(Messages.get().getBundle().key( 319 Messages.LOG_THREAD_POOL_WAITING_1, 320 new Integer (i))); 321 } 322 323 alive++; 327 m_workers[i].join(200); 328 } catch (InterruptedException e) { 329 } 331 } 332 } 333 } 334 335 int activeCount = m_threadGroup.activeCount(); 336 if (activeCount > 0 && LOG.isInfoEnabled()) { 337 LOG.info(Messages.get().getBundle().key( 338 Messages.LOG_THREAD_POOL_STILL_ACTIVE_1, 339 new Integer (activeCount))); 340 } 341 if (LOG.isDebugEnabled()) { 342 LOG.debug(Messages.get().getBundle().key(Messages.LOG_THREAD_POOL_SHUTDOWN_0)); 343 } 344 } 345 } 346 347 353 protected Runnable getNextRunnable() throws InterruptedException { 354 355 Runnable toRun = null; 356 357 synchronized (m_nextRunnableLock) { 360 if (m_nextRunnable == null) { 361 m_nextRunnableLock.wait(1000); 362 } 363 364 if (m_nextRunnable != null) { 365 toRun = m_nextRunnable; 366 m_nextRunnable = null; 367 m_nextRunnableLock.notifyAll(); 368 } 369 } 370 371 return toRun; 372 } 373 374 378 private void growThreadPool() { 379 380 if (m_currentThreadCount < m_maxThreadCount) { 381 synchronized (m_nextRunnableLock) { 383 m_workers[m_currentThreadCount] = new CmsSchedulerThread(this, m_threadGroup, m_threadNamePrefix 384 + m_currentThreadCount, m_threadPriority, m_makeThreadsDaemons); 385 if (m_inheritLoader) { 386 m_workers[m_currentThreadCount].setContextClassLoader(Thread.currentThread().getContextClassLoader()); 387 } 388 m_currentThreadCount++; 390 m_nextRunnableLock.notifyAll(); 392 } 393 } 394 } 395 } | Popular Tags |