With the default scope bean as singleton, wouldn't it be bad when parallel calls occur?

I declared a Spring bean that checks my mail server every so and so. If there is mail, it extracts it and tries to extract the attached files into it. These files are then sent to Uploader, which saves them safely. The user uploader is also declared as a Spring bean. The third bean associates the sender of the email with the file name and stores it in the database.

It turned out that when several people tried to send email at the same time, a bunch of messy things happened. Entries in the database received invalid file names. Some have not received file names, etc.

I explained this problem by the fact that beans is bound to singleton by default. This means that a bunch of threads are likely to get confused at the same time with the same instance. The question is how to solve this problem.

If I synchronize all sensitive methods, then all the threads will add up and wait for each other, which is not against the whole idea of โ€‹โ€‹multithreading.

On the other hand, viewing the beans request for a "request" will create new instances of each of them, which is also not very good when it comes to memory consumption and thread scheduling.

I'm confused. What should I do?

+8
java spring multithreading
source share
5 answers

I agree with the answers of @Bozho and @stivio.

The preferred parameters are to either skip stateless storage in a region with a single range of beans and pass the context object to the methods, or use the generated beans prototype / request created for each processing cycle. Synchronization can usually be avoided by choosing one of these approaches, and you get much more performance by avoiding deadlocks. Just make sure that you are not changing any general state like static members.

For each approach, there are pros and cons:

  • Singlton beans act like a class similar to a service, which some say is not a good object-oriented design.
  • Passing context to methods in a long chain of methods can make your code dirty if you are not careful.
  • The beans prototype can contain most of the memory longer than you planned, and can lead to memory exhaustion. You must be careful with the life cycle of these beans.
  • The prototype beans can make your design more neat. Make sure you do not reuse beans with multiple threads.

In most cases, I am inclined to a service approach. You can also allow these singleton beans to create a processing object that can contain its state for computation. This is the solution that can best help you in more complex scenarios.

Edit: There are times when you have a singleton bean depending on the scope bean prototype, and you want to create a new instance of the bean prototype for each method call. Spring offers several solutions for this:

The first uses the Injection method , as described in the Spring reference documentation. I do not like this approach because it makes your class be abstract.

The second is to use a ServiceLocatorFactoryBean or your own factory class (which needs to be injected with dependencies, and call the constructor). This approach works very well in most cases and does not bind you to Spring.

There are times when you also want the beans prototype to have run-time dependencies. My good friend wrote a good post about it here: http://techo-ecco.com/blog/spring-prototype-scoped-beans-and-dependency-injection/ .

+8
source share

Singleton-scoped beans should not contain any state - this usually solves the problem. If you only pass data as method parameters and do not assign them to fields, you will be safe.

+12
source share

Otherwise, just declare your beans request as a request, do not worry about memory consumption, garbage collection will clear it, as there will be enough memory, this is also not a performance problem.

+2
source share

Speaking abstractly: if you use Spring Integration, then you should create your code in terms of the messages themselves. For example, all important states should be propagated through messages. This makes scaling trivial by adding additional Spring Integration instances to handle the load. The only state (really) in Spring Integration is for components such as an aggregator that waits and collects messages that have correlation. In this case, you can delegate the backup storage, for example MongoDB, to process the data of these messages, and this, of course, is safe for threads.

More generally, this is an example of an event-driven architecture - components must be idle (N (1) no matter how many messages) process messages and then forward them over the pipe for consumption by another component that does not know about the previous component, from which the message came.

If you run into thread safety issues using Spring Integration, you can do something a little different than expected and it might be worth revisiting your approach ...

+2
source share

Singletones must be operable and thread safe.

If a singleton is stateless, this is a degenerate case of state preservation, and thread safety is trivial. But what's the point of being alone? Just create a new one every time someone asks.

If the instance is wealthy and not thread safe, then it should not be singleton; Each thread should have only a separate instance.

+1
source share

All Articles