设为首页 收藏本站
查看: 734|回复: 0

[经验分享] tomcat的ThreaadPool

[复制链接]

尚未签到

发表于 2015-8-8 09:13:06 | 显示全部楼层 |阅读模式
  在apache-tomcat-6.0.18-src\java\org\apache\tomcat\util\threads\里面
/*
*  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.tomcat.util.threads;
import java.util.*;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
* A thread pool that is trying to copy the apache process management.
*
* Should we remove this in favor of Doug Lea's thread package?
*
* @author Gal Shachor
* @author Yoav Shapira
*/
public class ThreadPool  {
private static Log log = LogFactory.getLog(ThreadPool.class);
private static StringManager sm =
StringManager.getManager("org.apache.tomcat.util.threads.res");
private static boolean logfull=true;
/*
* Default values ...
*/
public static final int MAX_THREADS = 200;
public static final int MAX_THREADS_MIN = 10;
public static final int MAX_SPARE_THREADS = 50;
public static final int MIN_SPARE_THREADS = 4;
public static final int WORK_WAIT_TIMEOUT = 60*1000;
/*
* Where the threads are held.
*/
protected ControlRunnable[] pool = null;
/*
* A monitor thread that monitors the pool for idel threads.
*/
protected MonitorRunnable monitor;

/*
* Max number of threads that you can open in the pool.
*/
protected int maxThreads;
/*
* Min number of idel threads that you can leave in the pool.
*/
protected int minSpareThreads;
/*
* Max number of idel threads that you can leave in the pool.
*/
protected int maxSpareThreads;
/*
* Number of threads in the pool.
*/
protected int currentThreadCount;
/*
* Number of busy threads in the pool.
*/
protected int currentThreadsBusy;
/*
* Flag that the pool should terminate all the threads and stop.
*/
protected boolean stopThePool;
/* Flag to control if the main thread is 'daemon' */
protected boolean isDaemon=true;
/** The threads that are part of the pool.
* Key is Thread, value is the ControlRunnable
*/
protected Hashtable threads=new Hashtable();
protected Vector listeners=new Vector();
/** Name of the threadpool
*/
protected String name = "TP";
/**
* Sequence.
*/
protected int sequence = 1;
/**
* Thread priority.
*/
protected int threadPriority = Thread.NORM_PRIORITY;

/**
* Constructor.
*/   
public ThreadPool() {
maxThreads = MAX_THREADS;
maxSpareThreads = MAX_SPARE_THREADS;
minSpareThreads = MIN_SPARE_THREADS;
currentThreadCount = 0;
currentThreadsBusy = 0;
stopThePool = false;
}

/** Create a ThreadPool instance.
*
* @param jmx UNUSED
* @return ThreadPool instance. If JMX support is requested, you need to
*   call register() in order to set a name.
*/
public static ThreadPool createThreadPool(boolean jmx) {
return new ThreadPool();
}
public synchronized void start() {
stopThePool=false;
currentThreadCount  = 0;
currentThreadsBusy  = 0;
adjustLimits();
pool = new ControlRunnable[maxThreads];
openThreads(minSpareThreads);
if (maxSpareThreads < maxThreads) {
monitor = new MonitorRunnable(this);
}
}
public MonitorRunnable getMonitor() {
return monitor;
}
/**
* Sets the thread priority for current
* and future threads in this pool.
*
* @param threadPriority The new priority
* @throws IllegalArgumentException If the specified
*  priority is less than Thread.MIN_PRIORITY or
*  more than Thread.MAX_PRIORITY
*/
public synchronized void setThreadPriority(int threadPriority) {
if(log.isDebugEnabled())
log.debug(getClass().getName() +
&quot;: setPriority(&quot; + threadPriority + &quot;): here.&quot;);
if (threadPriority < Thread.MIN_PRIORITY) {
throw new IllegalArgumentException(&quot;new priority < MIN_PRIORITY&quot;);
} else if (threadPriority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException(&quot;new priority > MAX_PRIORITY&quot;);
}
// Set for future threads
this.threadPriority = threadPriority;
Enumeration currentThreads = getThreads();
Thread t = null;
while(currentThreads.hasMoreElements()) {
t = (Thread) currentThreads.nextElement();
t.setPriority(threadPriority);
}
}
/**
* Returns the priority level of current and
* future threads in this pool.
*
* @return The priority
*/
public int getThreadPriority() {
return threadPriority;
}   

public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
}
public int getMaxThreads() {
return maxThreads;
}
public void setMinSpareThreads(int minSpareThreads) {
this.minSpareThreads = minSpareThreads;
}
public int getMinSpareThreads() {
return minSpareThreads;
}
public void setMaxSpareThreads(int maxSpareThreads) {
this.maxSpareThreads = maxSpareThreads;
}
public int getMaxSpareThreads() {
return maxSpareThreads;
}
public int getCurrentThreadCount() {
return currentThreadCount;
}
public int getCurrentThreadsBusy() {
return currentThreadsBusy;
}
public boolean isDaemon() {
return isDaemon;
}
public static int getDebug() {
return 0;
}
/** The default is true - the created threads will be
*  in daemon mode. If set to false, the control thread
*  will not be daemon - and will keep the process alive.
*/
public void setDaemon( boolean b ) {
isDaemon=b;
}
public boolean getDaemon() {
return isDaemon;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getSequence() {
return sequence;
}
public int incSequence() {
return sequence++;
}
public void addThread( Thread t, ControlRunnable cr ) {
threads.put( t, cr );
for( int i=0; i maxThreads) {
toOpen = maxThreads;
}
for(int i = currentThreadCount ; i < toOpen ; i++) {
pool[i - currentThreadsBusy] = new ControlRunnable(this);
}
currentThreadCount = toOpen;
}
/** @deprecated */
void log( String s ) {
log.info(s);
//loghelper.flush();
}
/**
* Periodically execute an action - cleanup in this case
*/
public static class MonitorRunnable implements Runnable {
ThreadPool p;
Thread     t;
int interval=WORK_WAIT_TIMEOUT;
boolean    shouldTerminate;
MonitorRunnable(ThreadPool p) {
this.p=p;
this.start();
}
public void start() {
shouldTerminate = false;
t = new Thread(this);
t.setDaemon(p.getDaemon() );
t.setName(p.getName() + &quot;-Monitor&quot;);
t.start();
}
public void setInterval(int i ) {
this.interval=i;
}
public void run() {
while(true) {
try {
// Sleep for a while.
synchronized(this) {
this.wait(interval);
}
// Check if should terminate.
// termination happens when the pool is shutting down.
if(shouldTerminate) {
break;
}
// Harvest idle threads.
p.checkSpareControllers();
} catch(Throwable t) {
ThreadPool.log.error(&quot;Unexpected exception&quot;, t);
}
}
}
public void stop() {
this.terminate();
}
/** Stop the monitor
*/
public synchronized void terminate() {
shouldTerminate = true;
this.notify();
}
}
/**
* A Thread object that executes various actions ( ThreadPoolRunnable )
*  under control of ThreadPool
*/
public static class ControlRunnable implements Runnable {
/**
* ThreadPool where this thread will be returned
*/
private ThreadPool p;
/**
* The thread that executes the actions
*/
private ThreadWithAttributes     t;
/**
* The method that is executed in this thread
*/
private ThreadPoolRunnable   toRun;
private Runnable toRunRunnable;
/**
* Stop this thread
*/
private boolean    shouldTerminate;
/**
* Activate the execution of the action
*/
private boolean    shouldRun;
/**
* Per thread data - can be used only if all actions are
*  of the same type.
*  A better mechanism is possible ( that would allow association of
*  thread data with action type ), but right now it's enough.
*/
private boolean noThData;
/**
* Start a new thread, with no method in it
*/
ControlRunnable(ThreadPool p) {
toRun = null;
shouldTerminate = false;
shouldRun = false;
this.p = p;
t = new ThreadWithAttributes(p, this);
t.setDaemon(true);
t.setName(p.getName() + &quot;-Processor&quot; + p.incSequence());
t.setPriority(p.getThreadPriority());
p.addThread( t, this );
noThData=true;
t.start();
}
public void run() {
boolean _shouldRun = false;
boolean _shouldTerminate = false;
ThreadPoolRunnable _toRun = null;
try {
while (true) {
try {
/* Wait for work. */
synchronized (this) {
while (!shouldRun && !shouldTerminate) {
this.wait();
}
_shouldRun = shouldRun;
_shouldTerminate = shouldTerminate;
_toRun = toRun;
}
if (_shouldTerminate) {
if (ThreadPool.log.isDebugEnabled())
ThreadPool.log.debug(&quot;Terminate&quot;);
break;
}
/* Check if should execute a runnable.  */
try {
if (noThData) {
if (_toRun != null) {
Object thData[] = _toRun.getInitData();
t.setThreadData(p, thData);
if (ThreadPool.log.isDebugEnabled())
ThreadPool.log.debug(
&quot;Getting new thread data&quot;);
}
noThData = false;
}
if (_shouldRun) {
if (_toRun != null) {
_toRun.runIt(t.getThreadData(p));
} else if (toRunRunnable != null) {
toRunRunnable.run();
} else {
if (ThreadPool.log.isDebugEnabled())
ThreadPool.log.debug(&quot;No toRun ???&quot;);
}
}
} catch (Throwable t) {
ThreadPool.log.error(sm.getString
(&quot;threadpool.thread_error&quot;, t, toRun.toString()));
/*
* The runnable throw an exception (can be even a ThreadDeath),
* signalling that the thread die.
*
* The meaning is that we should release the thread from
* the pool.
*/
_shouldTerminate = true;
_shouldRun = false;
p.notifyThreadEnd(this);
} finally {
if (_shouldRun) {
shouldRun = false;
/*
* Notify the pool that the thread is now idle.
*/
p.returnController(this);
}
}
/*
* Check if should terminate.
* termination happens when the pool is shutting down.
*/
if (_shouldTerminate) {
break;
}
} catch (InterruptedException ie) { /* for the wait operation */
// can never happen, since we don't call interrupt
ThreadPool.log.error(&quot;Unexpected exception&quot;, ie);
}
}
} finally {
p.removeThread(Thread.currentThread());
}
}
/** Run a task
*
* @param toRun
*/
public synchronized void runIt(Runnable toRun) {
this.toRunRunnable = toRun;
// Do not re-init, the whole idea is to run init only once per
// thread - the pool is supposed to run a single task, that is
// initialized once.
// noThData = true;
shouldRun = true;
this.notify();
}
/** Run a task
*
* @param toRun
*/
public synchronized void runIt(ThreadPoolRunnable toRun) {
this.toRun = toRun;
// Do not re-init, the whole idea is to run init only once per
// thread - the pool is supposed to run a single task, that is
// initialized once.
// noThData = true;
shouldRun = true;
this.notify();
}
public void stop() {
this.terminate();
}
public void kill() {
t.stop();
}
public synchronized void terminate() {
shouldTerminate = true;
this.notify();
}
}
/**
* Debug display of the stage of each thread. The return is html style,
* for display in the console ( it can be easily parsed too ).
*
* @return The thread status display
*/
public String threadStatusString() {
StringBuffer sb=new StringBuffer();
Iterator it=threads.keySet().iterator();
sb.append(&quot;&quot;);
while( it.hasNext()) {
sb.append(&quot;&quot;);
ThreadWithAttributes twa=(ThreadWithAttributes)
it.next();
sb.append(twa.getCurrentStage(this) ).append(&quot; &quot;);
sb.append( twa.getParam(this));
sb.append( &quot;\n&quot;);
}
sb.append(&quot;&quot;);
return sb.toString();
}
/** Return an array with the status of each thread. The status
* indicates the current request processing stage ( for tomcat ) or
* whatever the thread is doing ( if the application using TP provide
* this info )
*
* @return The status of all threads
*/
public String[] getThreadStatus() {
String status[]=new String[ threads.size()];
Iterator it=threads.keySet().iterator();
for( int i=0; ( i

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-95328-1-1.html 上篇帖子: 使用 Tomcat 7 新的连接池 —— Tomcat jdbc pool 下篇帖子: Tomcat配置https环境(Windows+Linux)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表