public class SingleThreadWebServer {
public static void main(String args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
Socket connection = socket.accept();
handleRequest(connection);
}
}
private static void handleRequest(Socket connection) {
System.out.println("do something");
}
}
public class MultipleThreadWebServer {
public static void main(String args[]) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable runable = new Runnable() {
public void run() {
handleRequest(connection);
}
};
new Thread(runable).start();
}
}
private static void handleRequest(Socket connection) {
System.out.println("do something");
}
}
SingleThreadWebServer很简单,且在理论上是正确的,但在实际生产环境中的执行性能却很槽糕,
因为它每次只能同时处理一个请求。主线程在接受连接域处理相关请求等操作之间不断地交替运行。当服
务器正在处理请求时,新到来的连接不许等待知道请求处理完成,然后服务器将再次调用accept。
MultipleThreadWebServer在结构上类似域前面的单线程版本-主线程仍然不断地交替执行“接受外部链接”
与”分发请求“ 等操作。区别于,对于每个连接,主线程都将创建一个新的线程来处理请求,而不是在祝循环
中进行处理。
基于Executor来构建web服务器是非常容易的。在程序中用Executor代替了硬编码的线程创建过程。在
这种情况下使用了一种标准的Executor实现,即一个固定长度的线程池,可以容纳100个线程。
public class TaskExcecutionWebServer {
private static final int NTHREADS= 100;
private static final Executor exe =
Executors.newFixedThreadPool(NTHREADS);
public static void main(String args[]) throws IOException{
ServerSocket socket =new ServerSocket(80);
while(true){
final Socket connection = socket.accept();
Runnable task =new Runnable() {
public void run() {
handleRequest(connection);
}
};
exe.equals(task);
}
}
}
在TaskExecutionWebServer中,通过使用Executor,将请求处理任务的提交域实际记性解耦开来,并且只需采用另一种
不同的Executor实现,就可以改变服务器的行为。改变Executor实现或配置所带来的影响要远远小于改变任务提交方式带来
的影响。通常,Executor的配置是一次性的,因此在不熟阶段可以完成,而提交任务的代码会不断地扩散到整个程序中,
增加了修改的难度。
public static ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r){
new Thread(r).start();
}
}