网站请求高并发 -- Servlet与IIS 线程处理 区别

 作为一个.net程序员,在开发java程序过程中总有些不解,比如这次我们在写接口的过程中,按照C#的思路,将变量写成了全局变量,java工程师看到这个问题后,认为这样写会导致线程不安全,为此展开了一系列的套路和测试(文章最后附上相关代码);主要套路了以下问题:

  • 在.net开发过程中很简单的东西为什么在java里面实现起来这么复杂;

  • 为什么java非常关注多线程的东西,而.net开发关注多线程就比较少;

  • 为什么iis对大数据并发支持的不是很好;

首先回答第一个问题:

​ 微软的c#设计者更注重一线开发人员的感受,为方便开发提高效率,他们愿意大费周章改善语言本身各方特性,不断加入语法糖,从泛型,nullable,隐式类型到lamada再到dynamic,awaitasyc等等都可看到其一直在围绕代码整洁,减少bug等实际的开发过程中问题来进行的改进,同时越来越智能的IDE也说明了这点。
​ 而java设计者则不同,他们的关注点在于java应用系统本身,更好的降低耦合,保持OOP是其始终坚持的。同时也应该不难发现,社区对java应用架构师提出的各类尖锐问题反馈总是较为及时,而对java应用开发者则相对冷淡些。

​ 可见两者出发点的思路不一样;

​ 第二个问题要和第三个问题一起回答:通常在.net的webapi中,多个地方用到了一个变量,我们会如下声明变量的,在正常的调用中,如果同时发起多个请求,每个请求给变量abc的赋值并不会被其他后面的请求给覆盖掉;但同样的代码,在java/Servlet中,后面请求参数将会把前面的参数给覆盖掉,也就是说这样写是线程不安全的;

​ 同样的代码: 两个请求间隔5秒执行,返回结果如下

  Request Response
.NET/IIS http://localhost:53906/api/Values/1 1
.NET/IIS http://localhost:53906/api/Values/2 2
Java/Tomcat http://localhost:53906/api/Values/1 2
Java/Tomcat http://localhost:53906/api/Values/2 2
 
     
1
2
3
4
5
6
7
 
     
int abc = 0;
public string Get(int id)
{
abc = id;
Thread.Sleep(15000);
return abc.ToString() ;
}

​ 可以看出同样的代码执行的结果却不一样;这个时候就牵涉到了两种语言和容器对多线程的处理逻辑;

在Java/Servlet 中,采用的是单实例多线程开发;当第一个用户发起请求后,Servlet将Class进行实例化,并分配线程调用的方法栈,当第二个请求来之后,还是使用的之前的实例,只是分配的线程方法栈不同,所以在类里面声明的全局变量,就会存在线程不安全的问题.这个时候需要将变量声明到方法体里面;

在.NET/IIS中,由于没有查询到相关的文档,猜测是多线程,非单例模式.没用IIS会为每个请求创建一个新的实例.这样的话,就不会存在java中的线程不安全问题;

​ 从上面的两个执行结果,我们就可以推断出,为什么java那么关心多线程而.net关心的就比较少,因为.net 的framework的执行中,避免了线程不安全的情况,可以让大家更方便省心的写代码;但同时带来了一个问题,也就是.net的处理方式会导致比java更多的开销,每当一个请求过来,都会声明一个实例,这样会带来大量的时间和空间开销.IIS同时处理的并发数也就比Tomcat等java容器高了;

个人博客原文链接

http://zhangzeshuai.com/2018/04/10/ThreadServletIIS/

猜你喜欢

转载自blog.csdn.net/zhangzeshuai/article/details/80151744