Java 满足高并发性时的简单web服务器
这不是一个家庭作业,而是我在网上找到的一个面试问题 java代码是:Java 满足高并发性时的简单web服务器,java,concurrency,Java,Concurrency,这不是一个家庭作业,而是我在网上找到的一个面试问题 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
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();
}
}
}
问题是,当存在高并发性时,会有什么潜在问题?我的分析是:
我看到的主要问题是你已经确定的问题。每个请求的线程模型本身就有缺陷(Nginx和lighttpd在Apache上的广泛采用证明了这一点)。在这里,转移到ExecutorService(可能由线程池支持)将是一个不错的选择 通过将每个请求的线程更改为向ExecutorService简单提交任务,可以将此应用程序移向基于事件的模型。网络上有很多宣传基于事件的模型优于基于线程的模型的可伸缩性优点的材料 在
handleRequest
方法上使用“synchronized”是一种非常暴力的策略,根据该方法的具体细节,最好使用更细粒度的锁定策略(或无锁逻辑)。您提到的ServerSocket创建对于应用程序只发生一次,因此这实际上不是一个可伸缩性问题。accept
方法确实为每个连接创建了一个新的Socket
实例,但这些都很便宜。查看JDK 6源代码,这包括分配7个布尔值、一个lock对象
,以及检查一些内部状态——也就是说,可能不会有问题
基本上,你在正确的轨道上!希望这有帮助。以下是潜在问题列表 1) 生成一个线程需要CPU周期,每个线程都有自己的数据结构,这会消耗内存。当一个线程阻塞时,JVM保存其状态并选择另一个线程运行,并恢复所选线程的状态,称为上下文切换。随着线程数量的增加,线程会消耗更多的资源。引入Threadpool是为了解决这个问题,它限制了线程的数量并重用线程,而不是产生新的线程 2) 最令人沮丧和最重要的问题是让这些线程以同步方式共享或访问变量(例如状态)。很容易使这些变量不一致。因此,一些程序员更喜欢使用单线程环境(例如NIO)而不是多线程环境 3) 当您想要追踪问题时,并没有日志记录系统将使线程环境更难调试 4) 您不需要在每次接受新客户机时都实例化new serversocket(),因为它是一个共享serversocket实例