这不是家庭作业,而是我在网上发现的面试问题。

Java代码是:

public class SimpleWebServer{
  public static void handleRequest(Socket c)
  {
    //Process the request
  }

  public static void main(String[] args) throws IOException
  {
    ServerSocket server=new ServerSocket(80);
    while(true)
    {
       final Socket connection=server.accept();
       Runnable task=new Runnable(){
          @Override
          public void run()
          {
            handleRequest(connection);
          }
       };
       new Thread(task).start();
    }
  }
}

问题是高并发性时会出现哪些潜在问题?我的分析是:
  • 它没有使用synced关键字,因此可能发生竞态情况。
  • 它应该使用一个更有效的线程池。
  • 似乎对于每个传入线程,该类总是创建一个新的ServerSocket,当发生高并发性时,它将占用大量空间吗?
  • 最佳答案

    我看到的主要问题是您已经确定的问题。每个请求线程模型固有地存在缺陷(Nginx和lighttpd相对于Apache的广泛采用证明了这一点)。移至ExecutorService(可能由线程池支持)在这里是一个不错的选择。

    通过从每个请求的线程更改为向ExecutorService的简单任务提交,您可以将此应用程序移至基于事件的模型。网络上有很多资料讲授基于事件的模型比基于线程的模型的可伸缩性优点。

    handleRequest方法上使用'synchronized'是一种蛮力策略,并且根据该方法的特定原理,更细粒度的锁定策略(或无锁定逻辑)将是首选。您提到的ServerSocket创建对于应用程序仅发生一次,因此这实际上不是可伸缩性问题。 accept方法的确为每个连接创建了一个新的Socket实例,但这很便宜。查看JDK 6源代码,这包括分配7个布尔值,一个锁Object并检查一些内部状态-即可能不会出现问题。

    基本上,您在正确的道路上!希望这可以帮助。

    10-06 13:47