tomcat容器实现类都继承了ContainerBase类,容器在启动的时候都会调用ContainerBase类的threadStart()方法,threadStart()方法如下:
- protected void threadStart() {
- if (thread != null)
- return;
- if (backgroundProcessorDelay <= 0)
- return;
- threadDone = false;
- String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
- thread = new Thread(new ContainerBackgroundProcessor(), threadName);
- thread.setDaemon(true);
- thread.start();
- }
StandardHost,StandardContext,StandardWrapper类的backgroundProcessorDelay的值都为-1,所以ContainerBackgroundProcessor线程都没有启动.而StandardEngine类在创建的时候 将backgroundProcessorDelay 的值设置为10.所以ContainerBackgroundProcessor线程在StandardEngine里启动,ContainerBackgroundProcessor线程代码如下:
- protected class ContainerBackgroundProcessor implements Runnable {
- public void run() {
- while (!threadDone) {
- try {
- Thread.sleep(backgroundProcessorDelay * 1000L);
- } catch (InterruptedException e) {
- ;
- }
- if (!threadDone) {
- Container parent = (Container) getMappingObject();//得到StandardEngine
- ClassLoader cl =
- Thread.currentThread().getContextClassLoader();
- if (parent.getLoader() != null) {
- cl = parent.getLoader().getClassLoader();
- }
- processChildren(parent, cl);
- }
- }
- }
- protected void processChildren(Container container, ClassLoader cl) {
- try {
- if (container.getLoader() != null) {
- Thread.currentThread().setContextClassLoader
- (container.getLoader().getClassLoader());
- }
- container.backgroundProcess();
- } catch (Throwable t) {
- log.error("Exception invoking periodic operation: ", t);
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
- Container[] children = container.findChildren();
- for (int i = 0; i < children.length; i++) {
- if (children[i].getBackgroundProcessorDelay() <= 0) {
- processChildren(children[i], cl);
- }
- }
- }
- }
ContainerBackgroundProcessor每隔10秒执行一下线程,线程递归调用StandardEngine,StandardHost,StandardContext,StandardWrapper类的backgroundProcess()方法(backgroundProcess()方法在ContainerBase类中)
backgroundProcess()方法如下:
- public void backgroundProcess() {
- if (!started)
- return;
- if (cluster != null) {
- try {
- cluster.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);
- }
- }
- if (loader != null) {
- try {
- loader.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e);
- }
- }
- if (manager != null) {//manager的实现类StandardManager
- try {
- manager.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e);
- }
- }
- if (realm != null) {
- try {
- realm.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);
- }
- }
- Valve current = pipeline.getFirst();
- while (current != null) {
- try {
- current.backgroundProcess();
- } catch (Exception e) {
- log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);
- }
- current = current.getNext();
- }
- lifecycle.fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
- }
在调用StandContext类的backgroundProcess()方法时, 会调用StandardManager的backgroundProcess()方法,该方法如下:
- public void backgroundProcess() {
- count = (count + 1) % processExpiresFrequency;
- if (count == 0)
- processExpires();
- }
processExpiresFrequency的默认值为6,所以每6*10秒会调一次processExpires()方法,processExpires()方法如下:
- public void processExpires() {
- long timeNow = System.currentTimeMillis();
- Session sessions[] = findSessions();
- int expireHere = 0 ;
- if(log.isDebugEnabled())
- log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);
- for (int i = 0; i < sessions.length; i++) {
- if (sessions[i]!=null && !sessions[i].isValid()) {//判断session是否有效,无效则清除
- expireHere++;
- }
- }
- long timeEnd = System.currentTimeMillis();
- if(log.isDebugEnabled())
- log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);
- processingTime += ( timeEnd - timeNow );
- }
该方法主要判断session是否过期,过期则清除.
整个过程看起来有点复杂,简单地来说,就是tomcat服务器在启动的时候初始化了一个守护线程,定期6*10秒去检查有没有Session过期.过期则清除.