单例Bean如何为并发请求提供服务?

关于单例bean如何详细地处理并发请求,我有一个问题。

我在StackOverflow上搜索过这个问题。 这是来自stackoverflow的示例链接 ,但我发现只有高级详细信息。 我想要了解单例bean如何服务并发请求以及系统处理器如何看到这些请求的完整细节。

我已经研究过在线系统处理器中的并发请求处理。 他们说处理器本身有一个调度程序,调度程序将决定处理哪个请求。

好的。 如果假设我有多个核心处理器,那么调度程序如何处理并发请求?

任何人都可以向我解释一个单例bean如何在JVM和系统中提供并发请求的分步过程吗?

让我用一个具体的例子来解释。 我有一个类似Sports的课程:

 class Sports { public void playFootball() { } public void playVolleyBall() { } } 

两个请求进来。第一个请求是在创建的Sports类的单例实例上执行playFootball方法。 同时,另一个请求是在类Sports的同一个创建的单例实例上执行playVolleyBall方法。

如何使用单例实例?

Saravan Kumar,

我理解你的问题背后的动机。 在我开始编写编译器之前,我也有一个非常相似的想要了解Java虚拟机的内部结构。

首先,我对你的问题印象深刻。 为了解决你的问题,需要有几点区分和理解。 首先:Singleton模式,有时甚至称为反模式,确保JVM只有一个此类实例可用。 这意味着我们基本上将全局状态引入应用程序。 我知道你理解这一点,但这只是一个澄清点。

现在是内部。

当我们创建一个类的实例时,我们正在创建一个驻留在JVM共享内存中的对象。 现在这些线程独立地执行在这些实例上运行的代码。 每个线程都有一个工作内存,在其中保存所有线程之间共享的主内存数据。 这是您创建的Singleton对象的引用所在的位置。 基本上发生的事情是生成的字节代码代表您创建的单例对象正在这些线程中的每一个上执行。

现在,如何发生这种情况的内部结构如下:

每个Java虚拟机线程都有一个私有Java虚拟机堆栈,与线程同时创建。 现在,Java虚拟机有一个在所有Java虚拟机线程之间共享的堆。 堆是运行时数据区,从中分配所有类实例和数组的内存。 堆是在虚拟机启动时创建的。 当你是线程请求单例实例时,它将指向堆中的引用,其中该Singleton的字节代码驻留在该引用中。 它将执行适当的代码,在您的情况下,它将执行第一个请求的第一个方法和第二个请求的第二个方法。 它能够执行此操作,因为没有锁或限制阻止编译器将程序计数器指向分配此实例的堆中的区域。 Singleton类对Java虚拟机的唯一限制是它在该类的堆中只能有一个实例。 就是这样。 除此之外,你可以从你的方法中引用它100倍,编译器将指向相同的字节代码并简单地执行它。 这就是为什么我们通常希望Singleton类是无状态的,因为如果我们任何线程访问它,我们不希望内部变量因为缺乏并发控制而变异。

请让我知道,如果你有任何问题!

理想的单身豆不应该保持任何状态。 这意味着它不会有任何变量存储特定于它所服务的请求的任何内容。

因此,单例bean将简单地具有无状态代码(例如,控制器方法),其可以针对多个请求并发地执行而没有任何并发​​问题。

例如,如果以下是您的单例bean:

 @Service public class Calculator { public int sum(int a, int b) { return a + b; } } 

简单来说,当两个“请求”同时调用bean的sum方法时,这意味着sum方法将在两个不同的线程中同时执行。 因此,他们将拥有自己的执行上下文,这些上下文不会相互重叠。 这样可以安全地允许它们同时运行。

如果同一个bean的状态如下:

 @Service public class Calculator { int incrementalMultiplier = 0; public int mulitply(int a, int b) { incrementalMultiplier++; return a * b * incrementalMultiplier; } } 

这可能会在同时提供两个请求时导致问题,因为incrementalMultiplier是将由两个请求(线程)共享的对象级别状态,因此可能会产生意外结果。

简而言之,无状态单例将能够同时处理两个请求,因为它们将位于不同的线程中。

我已经看到大量的警告让共享单例bean保持无状态,我想提出一个用例,其中Web应用程序支持bean中的有状态单例是有意义的。

我有一个管理Web应用程序,根据需要,查询两个独立的系统(CRM和数字资产管理器 – DAM)用于用户数据,比较记录,并相应地使用其API更新DAM。 如果有很多更新,这有时需要很长时间。 Web UI实时显示更新的状态,因为浏览器每秒使用ajax轮询支持bean以显示进度条以及它已处理的用户帐户数。 UI还提供了一个用于启动同步过程的按钮和一个用于停止同步过程的按钮。 最初启用同步按钮并且不显示停止按钮。 用户单击开始按钮后,将禁用启动按钮并启用停止按钮。

在同步处于活动状态时,我希望不同的客户端(键盘上的不同用户使用其各自浏览器中的Web应用程序)查看相同的状态,即进度条和处理的用户帐户数以及按钮状态。 这很重要,因为在已经进行第二个同步过程时启动第二个同步过程是没有意义的。

要详细了解单例Bean如何为并发请求提供服务? 你必须知道关于Spring Beans的以下内容

  • Bean范围

    Spring有不同的bean作用域(例如Prototype,Singleton等),但所有这些作用域都是在创建bean时强制执行的。 例如,每次“注入”此bean时,将创建“原型”范围的bean。 而“单例”范围的bean将被创建一次并在应用程序上下文中共享。
    “singleton”作用域是Spring Bean的默认范围。

  • 创建Bean

    Spring Bean的整个生命周期由Spring容器(即ApplicationContext / BeanFacotry)管理.Spring容器在内部引用bean定义(即基于XML的基于注释),用于创建由该bean定义定义的类的实际实例。 现在当Spring Container启动时,它引用bean定义并实例化所有已定义的bean。

  • 请求Bean。

    现在,当您的对象向bean发出请求时,Spring Container将切换已经初始化的bean。

  • 春豆范围

  • Spring对象是否安全?

  • Spring教程11 – 了解Bean范围

希望对你有帮助…

Singleton是一个bean范围。 您必须处理如何为multithreading访问提供服务。 您可以使用同步或并发包。 参考: Spring单例bean是线程安全的吗?

对于并发请求,单个bean将逐个为多个请求提供服务。