首先来看一下,任务的定义:
所谓的任务,就是抽象,离散的工作单位。你可以简单理解为代码级别的 (Runnable接口)
大多数并发应用程序都是围绕着任务进行管理的.
看一小段代码:
packagecom.ivan.concurrent.charpter6;importjava.net.ServerSocket;importjava.net.Socket;/*** 顺序化的Web Server.
*@authorroot
* OS:Ubuntu 9.04
* Date:2010-6-19*/
public classSingleThreadWebServer {public static void main(String[] args) throwsException {
ServerSocket server=new ServerSocket(8080);while(true){
Socket socket=server.accept();
handleRequest(socket);
}
}private static voidhandleRequest(Socket socket) {/*** 做相关的处理……, 比如请求运算与I/O
* 这将会导致出现阻塞, 会延迟当前请求的处理,
* 而且会产生非常严重的后果,比如: 假死。
* 那样会极度考验用户的耐心,知道他忍无可忍的关闭浏览器。
* 同时,单线程在等待IO操作时,CPU处于闲置状态,这样也降低了资源的利用率
*
* 这样的服务器,缺乏良好的吞吐量和快速的响应性。*/}
}
上面的代码是顺序地执行任务,主线程在不断接受连接与处理请求之间交替运行。
一个Web请求会做相关的处理……, 比如请求运算与I/O
这将会导致出现阻塞, 会延迟当前请求的处理,
而且会产生非常严重的后果,比如: 假死。
那样会极度考验用户的耐心,知道他忍无可忍的关闭浏览器。
同时,单线程在等待IO操作时,CPU处于闲置状态,这样也降低了资源的利用率
这样的服务器,缺乏良好的吞吐量和快速的响应性。
所以,基于上面代码的基础上,我们需要给他作些小许的改进:
packagecom.ivan.concurrent.charpter6;importjava.net.ServerSocket;importjava.net.Socket;public classThreadPerTaskWebServer {public static void main(String[] args) throwsException {
ServerSocket server=new ServerSocket(80);while(true){final Socket socket=server.accept();new Thread(newRunnable(){public voidrun() {
handleRequest(socket);
}
}).start();
}
}protected static voidhandleRequest(Socket socket) {/***相比较而言,这样的处理方式有良好的改进:
* 1.执行人物的负载已经脱离主线程,让主循环能更加迅速的重新开始等待下一个连接。提高了响应性
* 2.并发处理任务,多个请求可以同时得到处理,提高了吞吐性
* 3.任务处理代码必须要是线程安全的。防止出现并发性数据共享问题。
*
* 这个程序可能在开发阶段运行良好,一旦部署,就可能出现致命的错误,
* 我们接着来分析:*/}
}
相比较而言,这样的处理方式有良好的改进:
1.执行人物的负载已经脱离主线程,让主循环能更加迅速的重新开始等待下一个连接。提高了响应性
2.并发处理任务,多个请求可以同时得到处理,提高了吞吐性
3.任务处理代码必须要是线程安全的。防止出现并发性数据共享问题。
这个程序可能在开发阶段运行良好,一旦部署,就可能出现致命的错误,
我们接着来分析:
我们看到,上面的代码中,是为每个请求的到来,创建一个新的线程来处理, 那么这样就会有以下的问题出现:
无限创建线程的缺点:
1.线程生命周期的开销
1.1.线程的创建与关闭并非是免费的,实际的开销根据不同的OS有不同的处理.但是线程的创建的确需要时间,带来处理请求的延迟.一般的Web Server的请求是很频繁的,为每个请求创建一个线程&#