public class WorkerStack {
在AprEndpoint.class对线程池的管理有四个方法,令我感觉到奇怪是的没有初始化线程池
(1)protected Worker createWorkerThread(),此方法返一个可用的workThread,从线程池返回,如果线程池已无workThread,如满足条件则重新NEW一个,而满足的条件有二,现有线程数小于最大的线程数或是最大线程数为负数,因此在设置Tomcat线程池时把最大线程数设置为负数就可以创建任意多的工作线程
(2) protected Worker newWorkerThread(),此方返回新的workThread,并启动,即调用start()方法,线程嘛
(3) protected Worker getWorkerThread() ,返回一个可用的workThread,从功能上好像与createWorkerThread()重复,其实不然,因为createWorkerThread()有可能返回一个null,而此方法是确定能返回一个workThread
(4)protected void recycleWorkerThread(Worker workerThread) ,回收工作线程
Tomcat主要四个线程:
Acceptor:用于接浏览器的请求,serverSocket.accept();特别的是:连接socket是用tomcat native,Tomcat使用APR来提供超强的可伸缩性和性能,更好地集成本地服务器技术
Poller:与APR相关
Worker:工作线程,接收的socket就是交给工作线程处理
Sendfile:与APR相关
还有一个很重要的类,工作线程,Worker.class
源码:
public void run() {
// Process requests until we receive a shutdown signal
while (running) {
// Wait for the next socket to be assigned
long socket = await();
if (socket == 0)
continue;
// Process the request from this socket
if ((status != null) &&
(handler.event(socket, status) == Handler.SocketState.CLOSED)) {
// Close socket and pool
Socket.destroy(socket);
socket = 0;
} else if ((status == null) && ((options && !setSocketOptions(socket))
|| handler.process(socket) == Handler.SocketState.CLOSED)) {
// Close socket and pool
Socket.destroy(socket);
socket = 0;
}
// Finish up this request
recycleWorkerThread(this);
}
}
与《How Tomcat works》里的第四章讲的原理相同,都是从Acceptor线程接收socket,调用getWorkerThread() 方法得到工作线程,再调用工作线程的assign()方法,在《How Tomcat works》讲到await()与assign()并不是在同一个线程上,说起来也奇怪,在同一个类中竟然会在不同的线程中。令我不解的有几点:
(1)每一次都调用notifyAll()方法,会不会太浪费了?
notifyAll()的解释是唤醒在此对象监视器上等待的所有线程,synchronized 方法在this同步, 在此对象监视器只有两个线程,即工作线程与Acceptor线程。因此notifyAll()只是唤醒另一个线程,不会浪费。。。
(2)当一个工作线程正在运行的时候,此工作线程对象已不是线程池中,它的assign()方法又怎么可能会被调用呢?
(3)handler是每一个工作线程共享的,这样执行下去不会出现多线程安全问题?