最近想实现一个可携带状态的线程池,具体需求就是池中的线程被用来处理某种信息,而此信息可视为线程所依赖的外部状态。如果用简单的线程池来实现,线程初始化时就得赋予某些信息,使得线程无法被再次利用。在看老版Tomcat的源码时,找到了答案,其实现思路主要是利用了线程的等待和唤起,HttpProcessor的实现正好基于此思路,时序图如下所示:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/cutesource/EntryImages/20091226/httpProcessor.jpg)
初始化HttpProcessor线程时,没法赋予所需的Socket对象,因为如果在初始化阶段就赋予Socket会导致此线程没法回收用来处理其他Socket。因此,在HttpProcessor的run阶段,先把线程给wait住,具体在await方法里体现,代码如下所示:
-
-
-
-
- private synchronized Socket await() {
-
-
- while (!available) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
-
-
- Socket socket = this.socket;
- available = false;
- notifyAll();
-
- if ((debug >= 1) && (socket != null))
- log(" The incoming request has been awaited");
-
- return (socket);
-
- }
当HttpConnector调用HttpProcessor.assign(socket)方法时,会给此线程赋予Socket对象,并唤起此线程,使其继续执行,assign方法的源码如下所示:
-
-
-
-
-
-
-
-
-
- synchronized void assign(Socket socket) {
-
-
- while (available) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
-
-
- this.socket = socket;
- available = true;
- notifyAll();
-
- if ((debug >= 1) && (socket != null))
- log(" An incoming request is being assigned");
-
- }
线程被唤起和赋予socket对象后,继续执行核心的process方法,HttpProcessor.run的完整源码如下所示:
-
-
-
-
- public void run() {
-
-
- while (!stopped) {
-
-
- Socket socket = await();
- if (socket == null)
- continue;
-
-
- try {
- process(socket);
- } catch (Throwable t) {
- log("process.invoke", t);
- }
-
-
- connector.recycle(this);
-
- }
-
-
- synchronized (threadSync) {
- threadSync.notifyAll();
- }
-
- }