Original: Taste of Little Sister (wechat official ID: XjjDog), welcome to share, please reserve the source.

A long, long time ago, I had a painful memory. The feeling of being driven by a breakdown stuck in my mind for a long time.

For no other reason, someone has enabled the violent use of the thread pool. Yes, the following article.

Fatal failure! Blow up the investors!

I need to recap it briefly. The main reason is that developers create a separate thread pool for each method call. This way, if the volume of requests increases, the entire operating system will burn out and eventually all the business will become unresponsive.

I always thought this was a very occasional and low-level mistake that happened very infrequently. But as the number of such failures increased, XJJDog realized that this was a common phenomenon.

The purpose of asynchronous performance optimization is to make the whole service unavailable, which is a very humiliating optimization.

1.Spring asynchronous code

Spring is a Java sub-framework with an over-wrapped API that developers love. According to the logic of semantic programming, we can add keywords as long as they are acceptable at the language level. Like the @async annotation.

I can never figure out what gives developers the courage to add the @async annotation, because something that involves multithreading, even if you’re creating your own thread, is in awe of disturbing the operating system. Can @async black boxes really be used smoothly?

We might as well debug the code and let the bullet fly for a while.

First, generate a small project, then add the necessary annotations to the main class. Well, don’t forget this link, otherwise your annotations will be useless.

@SpringBootApplication
@EnableAsync
public class DemoApplication {

Copy the code

Create a method annotated @async.

@Component public class AsyncService { @Async public void async(){ try { Thread.sleep(1000); System.out.println(Thread.currentThread()); }catch (Exception ex){ ex.printStackTrace(); }}}Copy the code

Then, make a corresponding test interface that calls this async method when accessed.

@ResponseBody
@GetMapping("test")
public void test(){
    service.async();
}

Copy the code

When accessing, just hit a breakpoint to get the thread pool that executes the asynchronous thread.

As you can see, the asynchronous task uses a thread pool with corePoolSize=8 and the blocking queue uses the unbounded queue LinkedBlockingQueue. Once you use this combination, the maximum number of threads becomes meaningless, because tasks beyond eight threads will all be placed in an unbounded queue. The following code becomes a decoration.

throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, var4);

Copy the code

If you get a lot of traffic, these tasks will pile up in your LinkedBlockingQueue. At better times, the execution of these tasks becomes significantly delayed; In worse cases, too many tasks will directly cause memory overflow.

You might say, I can specify another ThreadPoolExceute myself and declare it with the @async annotation. The students who said this must have strong ability, or have less Review code, and have not been baptized by pig teammates.

2. SpringBoot saves you

SpringBoot is a good thing.

By generating in TaskExecutionAutoConfiguration ThreadPoolTaskExecutor Bean, to provide the default Executor.

@ConditionalOnMissingBean({Executor.class})
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
    return builder.build();
}

Copy the code

The one we talked about above. Without the help of SpringBoot, Spring will default to SimpleAsyncTaskExecutor.

See org. Springframework. Aop. Interceptor. AsyncExecutionInterceptor.

@Override @Nullable protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) { Executor defaultExecutor = super.getDefaultExecutor(beanFactory); return (defaultExecutor ! = null ? defaultExecutor : new SimpleAsyncTaskExecutor()); }Copy the code

This is what the Great Fairy of Spring does.

The SimpleAsyncTaskExecutor class is designed to be a mess because it creates a separate thread each time it executes, with no shared thread pool at all. For example, if your TPS is 1000 and you execute tasks asynchronously, you will generate 1000 threads per second!

This is a clear attempt to beat the rhythm of the operating system.

protected void doExecute(Runnable task) { Thread thread = (this.threadFactory ! = null ? this.threadFactory.newThread(task) : createThread(task)); thread.start(); }Copy the code

3.End

At first glance, this approach to using the new thread would be very scary. But in Spring itself, there are plenty of references to the SimpleAsyncTaskExecutor class, including the more popular AsyncRestTemplate.

This exposes a number of risks, not least the fact that Redis appears on these lists. The design of this class makes the execution of tasks very uncontrollable.

Looking at this API, I feel like Spring has gone into a design frenzy.

The hidden bugs on this thing could be even deeper! Such as org. Springframework. Context. Event. EventListener annotations, used to implement the DDD that set of so-called event-driven mode, there are a number of frame and set the AsyncRestTemplate directly, then you die.

Add SimpleAsyncTaskExecutor to your API blacklist, or pit list!

Is it that hard to create a thread? Need threads created using Spring? Sometimes I can’t figure out what the purpose of exposing such interfaces is.

Even if we don’t understand the native thread pool, you have also included a layer, which is convenient for us to blame!

Xjjdog is a public account that doesn’t allow programmers to get sidetracked. Focus on infrastructure and Linux. Ten years architecture, ten billion daily flow, and you discuss the world of high concurrency, give you a different taste. My personal wechat xjjdog0, welcome to add friends, further communication.

Recommended reading:

2. What does the album taste like

3. Bluetooth is like a dream 4. 5. Lost architect, leaving only a script 6. Bugs written by architect, unusual 7. Some programmers, nature is a flock of sheep!

Taste of little sister

Not envy mandarin duck not envy fairy, a line of code half a day

324 original content