JAVA简易WEB服务器(五)

原创 2016年02月26日 15:07:56

在之前的几篇博客中,我们的服务器已经具备雏形了,我们还需要继续对其进行优化,在《JAVA简易WEB服务器(三)》中,我们启动服务器的方法如下:

 /**
  * 启动服务器
  */
 public synchronized void start()
 {
    try
    {
       serverSocket = new ServerSocket(port);
       LOG.info("server init success.");
    }
    catch (IOException e)
    {
       LOG.log(Level.SEVERE, e.getMessage(), e);
    }
    new Thread()
    {
       public void run()
       {
          while (!isStop())
          {
             Socket socket;
             try
             {
                socket = serverSocket.accept();
                handleRequest(socket);
             }
             catch (IOException e)
             {
                LOG.log(Level.SEVERE, e.getMessage(), e);
             }
          }
       };
    }.start();
 }

我们是在一个线程中启动我们的服务器,避免阻塞主线程,但是这样,依然存在的问题是,我们的服务器一次只能处理一个请求,这样肯定是不合理的,所以在这一篇博客中,我们将使用多线程对服务端进行优化。

进一步的优化方式:使用多线程,我们可以在接收到请求后开辟新线程进行处理,代码如下:

/**
  * 启动服务器
  */
 public synchronized void start2()
 {
    try
    {
       serverSocket = new ServerSocket(port);
       LOG.info("server init success.");
    }
    catch (IOException e)
    {
       LOG.log(Level.SEVERE, e.getMessage(), e);
    }
    new Thread()
    {
       public void run()
       {
          while (!isStop())
          {
              try
             {
                final Socket socket = serverSocket.accept();
                new Thread()
                {
                   public void run()
                   {
                      try
                      {
                         handleRequest(socket);
                      }
                      catch (IOException e)
                      {
                        LOG.log(Level.SEVERE, e.getMessage(), e);
                     }
                  };
               }.start();
            }
            catch (IOException e)
            {
               LOG.log(Level.SEVERE, e.getMessage(), e);
            }
         }
      };
   }.start();
}

这里,一旦TCP连接建立之后,将会创建一个新的线程来处理新的请求,在新的线程中执行handleRequest方法。
通过创建新的线程,程序可以继续接受新的TCP连接,且这些请求可以并行的处理。
在每个请求一个线程实现中,创建一个线程(和后续的销毁)开销是非常昂贵的,因为JVM和操作系统都需要分配资源。另外,上面的实现还有一个问题,即创建的线程数是不可控的,这将可能导致系统资源被迅速耗尽。
所以我们应该继续寻找解决方案:线程池
使用线程池可以更好的管理我们创建的线程,JDK为我们提供了几种默认的线程池实现,当线程池满后,后续的请求我们是用丢弃的策略,所以在这里面们使用自定义的线程池,完整的HQHttpServer代码如下:

package com.gujin.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import com.gujin.server.utils.HQClose;

/**
 * 服务端
 * 
 * @author jianggujin
 * 
 */
public abstract class HQHttpServer implements HQHttpServerLog
{
   /** 端口号 **/
   private int port = 80;
   /** 服务套接字 **/
   private ServerSocket serverSocket = null;
   private int poolSize = 4;
   private int capacity = 16;

   /**
    * 默认构造方法
    */
   public HQHttpServer()
   {
   }

   /**
    * 构造方法
    * 
    * @param port
    */
   public HQHttpServer(int port)
   {
      this.port = port;
   }

   public int getPoolSize()
   {
      return poolSize;
   }

   public void setPoolSize(int poolSize)
   {
      this.poolSize = poolSize;
   }

   public int getCapacity()
   {
      return capacity;
   }

   public void setCapacity(int capacity)
   {
      this.capacity = capacity;
   }

   /**
    * 异步启动服务器
    */
   public void startAsyn()
   {
      new Thread()
      {
         public void run()
         {
            start();
         };
      }.start();
   }

   /**
    * 启动服务器
    * 
    * @throws IOException
    */
   public synchronized void start() throws IOException
   {
      if (isStop())
      {
         serverSocket = new ServerSocket(port);
         LOG.info("server init success.");
         ExecutorService executorService = newBoundedFixedPool(poolSize,
               poolSize);
         while (!isStop())
         {
            Socket socket = serverSocket.accept();
            LOG.info("accept client...");
            executorService.submit(new HQSocketRunnable(socket));
         }
      }
   }

   /**
    * 处理请求
    * 
    * @param socket
    * @throws IOException
    */
   protected void handleRequest(Socket socket) throws IOException
   {
      HQRequest request = new HQRequest(socket);
      request.execute();
      HQResponse response = new HQResponse(socket);
      try
      {
         response.setCookieHandler(request.getCookieHandler().clone());
      }
      catch (CloneNotSupportedException e)
      {
         LOG.log(Level.SEVERE, e.getMessage(), e);
      }
      handleRequest(request, response);
      response.response();
      HQClose.safeClose(socket);
   }

   /**
    * 处理请求
    * 
    * @param request
    * @param response
    * @throws IOException
    */
   public abstract void handleRequest(HQRequest request, HQResponse response)
         throws IOException;

   /**
    * 是否停止
    * 
    * @return
    */
   public boolean isStop()
   {
      return serverSocket == null || serverSocket.isClosed();
   }

   /**
    * 停止服务器
    */
   public synchronized void stop()
   {
      if (!isStop())
      {
         HQClose.safeClose(serverSocket);
         serverSocket = null;
      }
   }

   public static ExecutorService newBoundedFixedPool(int nThreads, int capacity)
   {
      return new ThreadPoolExecutor(nThreads, nThreads, 0L,
            TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>(capacity),
            new ThreadPoolExecutor.DiscardPolicy());
   }

   private class HQSocketRunnable implements Runnable
   {
      private Socket socket = null;

      public HQSocketRunnable(Socket socket)
      {
         this.socket = socket;
      }

      @Override
      public void run()
      {
         try
         {
            handleRequest(socket);
         }
         catch (Exception e)
         {
            LOG.log(Level.SEVERE, e.getMessage(), e);
         }
      }
   }
}
版权声明:本文为博主原创文章,转载请标明出处。

相关文章推荐

JAVA简易WEB服务器(一)

这一篇博客开始将和大家一起使用JAVA编写一个简易的Web服务器。 众所周知Web服务器与客户端之间的通信是使用HTTP协议的。HTTP是一个客户端和服务器端请求和应答的标准(TCP)。因为HTTP...

JAVA简易WEB服务器(四)

在之前的博客中,我们完成了WEB服务器的请求解析以及响应,达到了最基本的要求,我们都知道WEB服务器在处理请求的时候可以获得客户端提交的参数外,还可以获得Cookie信息,响应的时候也会对Cookie...

简易WEB服务器

  • 2014-01-18 08:42
  • 635KB
  • 下载

socket封装简易web服务器

  • 2017-03-15 23:03
  • 22KB
  • 下载

ASP.NET一个简易的WebServer,用控制台程序模拟IIS服务器 托起web服务

写了一个简单WebServer 服务器,可以处理js、css、html、aspx的请求,以及图片、视频 代码如下: public delegate void ProcessRequestHan...

简易静态Web服务器

用Web api /Nancy 通过Owin Self Host简易实现一个 Http 服务器

过去做 端游的Http 服务器 用的WebApi 或者Mvc架构,都是放在iis。。。而我已经是懒出一个地步,并不想去配iis,或者去管理iis,所以我很喜欢 Self host 的启动方式。C#做 ...

自己动手开发简易的Web服务器

使用python实现一个简易版的web服务器,旨在了解web服务器的工作原理,及了解HTTP协议。没有涉及多线程处理,并发之类的内容,以后再专门另外研究。
  • yagas
  • yagas
  • 2015-07-06 21:40
  • 991
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)