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

时间:2022-10-30 09:13:59

I have a question regarding how singleton beans serve concurrent requests in detail.

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

I have searched on * regarding this question. This is a sample link from *, but I found only high level details. I want full details on how a singleton bean serves concurrent requests and how the system processor will see those requests.

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

I have researched regarding concurrent request handling in the system processor online. They said the processor itself has a scheduler and that scheduler will decide which request gets processed.

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

Ok fine. If suppose I have more than one core processor, how does the scheduler handle concurrent requests?

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

Can anyone explain to me the step-by-step process on how a singleton bean will serve concurrent requests in the JVM and system?

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

Let me explain with a concrete example. I have a class like Sports:

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

class Sports {
    public void playFootball() {
    }

    public void playVolleyBall() {
    }
}

Two requests come in. The first request is executing the playFootball method on the created singleton instance of class Sports. At the same time, another request is executing the playVolleyBall method on the same created singleton instance of class Sports.

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

How is it possible with a singleton instance?

如何使用单例实例?

5 个解决方案

#1


55  

Saravan Kumar,

I understand the motivation behind your question. Before I started working on compilers, I also had a very similar wanting to know the internals of the Java Virtual Machine.

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

First of all, I'm impressed by your question. There needs to be a couple of points of distinctions and understanding in order to solve your question. Firstly: A Singleton pattern, or sometimes even called an anti-pattern, ensures that there is only one instance of this class available to the JVM. This means we're essentially introducing a global state into an application. I know you understand this, but it is just a point of clarification.

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

Now the internals.

现在是内部。

When we create an instance of a class, we are creating an object that is residing in JVM's shared memory. Now these threads are independently executing code that operates on these instances. Each thread has a working memory, in which it keeps data from the main memory that are shared between all threads. This is where the reference to the Singleton object you have create resides. Essentially what is happening is that the byte code which was generated and is representative of the singleton object you created is being executed on each one of these threads.

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

Now the internals of how this happens is as follows:

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

Each Java virtual machine thread has a private Java virtual machine stack, created at the same time as the thread. Now, The Java virtual machine has a heap that is shared among all Java virtual machine threads. The heap is the runtime data area from which memory for all class instances and arrays is allocated. The heap is created on virtual machine start-up. When you're thread requests the singleton instance, it is going to point to a reference in the heap where the byte code for this Singleton resides. It is going to execute the appropriate code, in your case it's going to execute the first method for the first request and the second method for the second request. It's able to do this because there are no locks or restriction preventing the compiler from pointing the program counter to the area in the heap where this instance is allocated. The only restriction that the Singleton class puts on the Java Virtual Machine is that it can have only one instance in the heap of this class. That's simply it. Other than that, you can refer to it 100x times from your method, the compiler is going to point to the same byte code and simply execute it. This is why we typically want the Singleton class to be stateless, because if we any thread access it, we don't want internal variables to be mutated because of the lack of concurrency control.

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

Please let me know if you have any questions!

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

#2


12  

An ideal singleton bean should not keep any state. That means it will not have any variables that store anything specific to the request it is serving.

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

Thus, a singleton bean will simply have stateless code (e.g. controller methods) that can be executed concurrently for multiple requests without any concurrency issues.

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

For example if following was your singleton bean:

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

@Service
public class Calculator {

   public int sum(int a, int b) {
        return a + b;
   } 

}

In simple terms, when two "requests" invoke sum method of the bean at the same time, that would mean the sum method would be executed concurrently in two different threads. Hence they will have their own execution context which wont overlap with each other. This would safely allow them to run concurrently.

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

If the same bean was to have state as follows:

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

@Service
public class Calculator {

   int incrementalMultiplier = 0;

   public int mulitply(int a, int b) {
        incrementalMultiplier++;
        return a * b * incrementalMultiplier;
   } 

}

This could cause issues when serving two requests concurrently because the incrementalMultiplier is the object level state that will be shared by the two requests (threads) and hence could produce unexpected results.

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

In short a stateless singleton will be able to serve two requests concurrently because they will be in different threads.

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

#3


2  

I've seen plenty of admonishments to keep shared singleton beans stateless and I wanted to present a use case where a stateful singleton in a web app backing bean makes sense.

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

I have an administrative web app that, on demand, queries two separate systems (a CRM and a Digital Assets Manager - DAM) for user data, compares the records, and updates the DAM accordingly using its API. This sometimes takes a very long time if there are a lot of updates. The web UI displays the status of the updates in real time, as the browser polls the backing bean using ajax every second to display a progress bar and how many user accounts it has processed. The UI also provides a button to start the sync process and a button to stop it. The sync button is initially enabled and the stop button is not rendered. After the user clicks the start button, the start button is disabled and the stop button rendered enabled.

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

While the sync is active, I want different clients (different users at the keyboard using the web app in their separate browsers) to see the same state, i.e. the progress bar and number of user accounts processed and the button states. This is important because it makes no sense to kick off a second sync process while one is already in process.

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

#4


0  

To know in details How does the singleton Bean serve the concurrent request? you have to know the following things about Spring Beans

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

  • Bean scopes

    Spring has different bean scopes (e.g. Prototype, Singleton, etc.) but all these scopes enforce is when the bean is created. For example a "prototype" scoped bean will be created each time this bean is "injected". whereas a "singleton" scoped bean will be created once and shared within the application context.
    "singleton" scoped is default scope of Spring Bean.

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

  • Creation of Bean

    创建Bean

    The whole life cycle of Spring Bean is managed by the Spring Container (i.e. ApplicationContext/BeanFacotry) Spring Container internally refers the bean definition (i.e.XML base ot Annotation based) for creating actual instances of the class defined by that bean definition. now when Spring Container get started it refers to the bean definition and instatiate all the defined bean.

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

  • Request the Bean.

    请求Bean。

    Now when your object make a request to the bean then Spring Container will handover the bean which allready initialized.

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

  • Spring Bean Scope

    春豆范围

  • Are Spring objects thread safe?

    Spring对象是否安全?

  • Spring Tutorial 11 - Understanding Bean Scopes

    Spring教程11 - 了解Bean范围

hope this will help you...

希望对你有帮助...

#5


-1  

Singleton is a bean scope. You have to handle that how to serve for multiple thread access. You can use synchronization or concurrent pakages. Ref: Are Spring singleton beans thread-safe?

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

For concurrent request, single bean will serve for mutliple requests one by one.

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

#1


55  

Saravan Kumar,

I understand the motivation behind your question. Before I started working on compilers, I also had a very similar wanting to know the internals of the Java Virtual Machine.

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

First of all, I'm impressed by your question. There needs to be a couple of points of distinctions and understanding in order to solve your question. Firstly: A Singleton pattern, or sometimes even called an anti-pattern, ensures that there is only one instance of this class available to the JVM. This means we're essentially introducing a global state into an application. I know you understand this, but it is just a point of clarification.

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

Now the internals.

现在是内部。

When we create an instance of a class, we are creating an object that is residing in JVM's shared memory. Now these threads are independently executing code that operates on these instances. Each thread has a working memory, in which it keeps data from the main memory that are shared between all threads. This is where the reference to the Singleton object you have create resides. Essentially what is happening is that the byte code which was generated and is representative of the singleton object you created is being executed on each one of these threads.

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

Now the internals of how this happens is as follows:

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

Each Java virtual machine thread has a private Java virtual machine stack, created at the same time as the thread. Now, The Java virtual machine has a heap that is shared among all Java virtual machine threads. The heap is the runtime data area from which memory for all class instances and arrays is allocated. The heap is created on virtual machine start-up. When you're thread requests the singleton instance, it is going to point to a reference in the heap where the byte code for this Singleton resides. It is going to execute the appropriate code, in your case it's going to execute the first method for the first request and the second method for the second request. It's able to do this because there are no locks or restriction preventing the compiler from pointing the program counter to the area in the heap where this instance is allocated. The only restriction that the Singleton class puts on the Java Virtual Machine is that it can have only one instance in the heap of this class. That's simply it. Other than that, you can refer to it 100x times from your method, the compiler is going to point to the same byte code and simply execute it. This is why we typically want the Singleton class to be stateless, because if we any thread access it, we don't want internal variables to be mutated because of the lack of concurrency control.

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

Please let me know if you have any questions!

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

#2


12  

An ideal singleton bean should not keep any state. That means it will not have any variables that store anything specific to the request it is serving.

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

Thus, a singleton bean will simply have stateless code (e.g. controller methods) that can be executed concurrently for multiple requests without any concurrency issues.

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

For example if following was your singleton bean:

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

@Service
public class Calculator {

   public int sum(int a, int b) {
        return a + b;
   } 

}

In simple terms, when two "requests" invoke sum method of the bean at the same time, that would mean the sum method would be executed concurrently in two different threads. Hence they will have their own execution context which wont overlap with each other. This would safely allow them to run concurrently.

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

If the same bean was to have state as follows:

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

@Service
public class Calculator {

   int incrementalMultiplier = 0;

   public int mulitply(int a, int b) {
        incrementalMultiplier++;
        return a * b * incrementalMultiplier;
   } 

}

This could cause issues when serving two requests concurrently because the incrementalMultiplier is the object level state that will be shared by the two requests (threads) and hence could produce unexpected results.

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

In short a stateless singleton will be able to serve two requests concurrently because they will be in different threads.

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

#3


2  

I've seen plenty of admonishments to keep shared singleton beans stateless and I wanted to present a use case where a stateful singleton in a web app backing bean makes sense.

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

I have an administrative web app that, on demand, queries two separate systems (a CRM and a Digital Assets Manager - DAM) for user data, compares the records, and updates the DAM accordingly using its API. This sometimes takes a very long time if there are a lot of updates. The web UI displays the status of the updates in real time, as the browser polls the backing bean using ajax every second to display a progress bar and how many user accounts it has processed. The UI also provides a button to start the sync process and a button to stop it. The sync button is initially enabled and the stop button is not rendered. After the user clicks the start button, the start button is disabled and the stop button rendered enabled.

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

While the sync is active, I want different clients (different users at the keyboard using the web app in their separate browsers) to see the same state, i.e. the progress bar and number of user accounts processed and the button states. This is important because it makes no sense to kick off a second sync process while one is already in process.

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

#4


0  

To know in details How does the singleton Bean serve the concurrent request? you have to know the following things about Spring Beans

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

  • Bean scopes

    Spring has different bean scopes (e.g. Prototype, Singleton, etc.) but all these scopes enforce is when the bean is created. For example a "prototype" scoped bean will be created each time this bean is "injected". whereas a "singleton" scoped bean will be created once and shared within the application context.
    "singleton" scoped is default scope of Spring Bean.

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

  • Creation of Bean

    创建Bean

    The whole life cycle of Spring Bean is managed by the Spring Container (i.e. ApplicationContext/BeanFacotry) Spring Container internally refers the bean definition (i.e.XML base ot Annotation based) for creating actual instances of the class defined by that bean definition. now when Spring Container get started it refers to the bean definition and instatiate all the defined bean.

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

  • Request the Bean.

    请求Bean。

    Now when your object make a request to the bean then Spring Container will handover the bean which allready initialized.

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

  • Spring Bean Scope

    春豆范围

  • Are Spring objects thread safe?

    Spring对象是否安全?

  • Spring Tutorial 11 - Understanding Bean Scopes

    Spring教程11 - 了解Bean范围

hope this will help you...

希望对你有帮助...

#5


-1  

Singleton is a bean scope. You have to handle that how to serve for multiple thread access. You can use synchronization or concurrent pakages. Ref: Are Spring singleton beans thread-safe?

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

For concurrent request, single bean will serve for mutliple requests one by one.

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