How to solve the problems of Java's three Blocking Queues

Recently, I and my team of programmers have discovered a minor obstacle to the application's request mechanism. After some checks, I found the root cause.

Disability and diagnosis

The thread pool for processing requests for the application was full and could not handle additional requests. After dumping the threads, I found that the thread stack was blocked in the log write area. Blocking the thread stack in the log write area is not a new issue, but I used to think this was the result of something else. Therefore, based on past experience, we have assumed that the problem is not in the log write area.

After using a lot of troubleshooting and frustrating without finding the root cause of the problem, we looked at the source code and tried to get some clues as to what was causing the problem. .. I found that my code has a log lock. From this log lock, we can see that there is a block in ArrayBlockingQueue.put from the thread stack. Further investigation revealed that it was a 1024-long Blocking Queue. What this means is that if you have 1024 objects in this queue, subsequent put requests will be blocked.

The programmer who wrote this code seemed to think that the data should be processed once the BlockingQueue is full. The code in question is below.

if (blockingQueue.retainCapacity() < 1) { //todo } blockingQueue.put

There are two main parts to the problem here.

  1. A complete verdict goes directly to "put" instead of "else".

  2. Even after the queue is full, the processing logic is // todo ...

The code above shows that this particular programmer is not familiar with the BlockingQueue interface. You do not need to make this decision first to get this result. A better way would be to use blockingQueue.offer. If this returns as'false', you can implement the relevant exception handling.

Blocking Queues type

BlockingQueue is a commonly used data structure in production / consumer mode. The most commonly used types are ArrayBlockingQueue, LinkedBlockingQueue, and SynchronousQueue.

The main difference between ArrayBlockingQueue and LinkedBlockingQueue is the objects that are placed in the queue. One is used for arrays and the other is used for linked tables. Other differences are also mentioned in the code notes.

Linked queues typically have higher throughput than array-based queues, but with poor predictable performance for most concurrent applications.

SynchronousQueue is a special BlockingQueue. It is used during offer. If no other thread is currently taking or polling, the offer will fail. It will also fail if no other thread is running offer at the same time during the take. This special mode is suitable for threads from queues and non-fixed thread pools that have high response requirements.

Problem overview

Online business scenarios require a timeout mechanism in all areas where concurrency and external access are blocked. I don't know how many times I've seen the lack of a timeout mechanism at the root cause of serious disruption to online business. Online business focuses on processing and completing requests quickly. Therefore, fast failure is the most important principle in the design of online business systems and code programming. According to this principle, the most obvious mistake in the code above is to use put instead of offer, which uses the timeout mechanism. Alternatively, in non-essential scenarios, offer should be used directly, and the result of'false'can be said to cause direct exceptions to be thrown or logged.

For BlockingQueue scenarios, you must limit the queue length in addition to the timeout mechanism. Otherwise, Integer. MAX_VALUE is used by default. In this case, a bug in the code will cause the memory to stop.

When we talk about BlockingQueue, we also mention the most used area of BlockingQueue, the thread pool.

ThreadPoolExecutor has a BlockingQueue parameter. If ArrayBlockingQueue or LinkedBlockingQueue is used here and the coreSize and poolSize of the thread pool are different, the thread pool will first be offered to the BlockingQueue after the coreSize thread is occupied. Will be sent. If successful, the process ends. However, this scenario does not always fit the needs of online business.

Online businesses operate in a fast-paced environment and require fast processing as opposed to placing requests in queues. In fact, it's best for online business if the requests aren't queued at all. This kind of online business structure is easily broken, and it's a relatively simple but good way to directly reject a request that exceeds the capacity of the system and issue an error message instead. .. But it's a limited mechanism.

Keep in mind that when writing highly concurrent and distributed code, it is important to pay attention not only to the system design, but also to the details of the code. By doing so, you can avoid the above problems.

Recommended Posts

How to solve the problems of Java's three Blocking Queues
How to determine the number of parallels
How to sort the List of SelectItem
How to output the sum of any three numbers, excluding the same value
How to solve the local environment construction of Ruby on Rails (MAC)!
[Rails] How to solve the time lag of created_at after save method
How to find the cause of the Ruby error
Customize how to divide the contents of Recyclerview
How to get today's day of the week
Output of how to use the slice method
How to display the result of form input
[Java] How to get the authority of the folder
[Java] How to get the URL of the transition source
How to write Scala from the perspective of Java
[Ruby] How to find the sum of each digit
[Java] How to get the maximum value of HashMap
[Rails] How to change the column name of the table
[SwiftUI] How to specify the abbreviated position of Text
[Android] How to get the setting language of the terminal
[Rails] How to get the contents of strong parameters
How to judge the click of any area of the image
How to download the old version of Apache Tomcat
[Swift] How to get the document ID of Firebase
How to set the retry limit of sidekiq and notify dead queues with slack
How to display the select field of time_select every 30 minutes
How to get the longest information from Twitter as of 12/12/2016
[Ruby] How to retrieve the contents of a double hash
How to add elements without specifying the length of the array
Let's summarize how to extend the expiration date of Rails
Median of the three values
[Rails] How to display the list of posts by category
How to mock some methods of the class under test
How to derive the last day of the month in Java
How to change the contents of the jar file without decompressing
How to check the extension and size of uploaded files
[jsoup] How to get the full amount of a document
How to check the database of apps deployed on Heroku
I tried to solve the problem of "multi-stage selection" with Ruby
[Swift] How to dynamically change the height of the toolbar on the keyboard
[Rails] How to get the URL of the transition source and redirect
[Swift5] How to get an array and the complement of arrays
How to set the IP address and host name of CentOS8
How to display 0 on the left side of the standard input value
[Tips] How to solve problems with XCode and Swift for beginners
[Rails / Heroku / MySQL] How to reset the DB of Rails application on Heroku
[Swift UI] How to get the startup status of the application [iOS]
How to get the contents of Map using for statement Memorandum
[Rails] How to omit the display of the character string of the link_to method
[Rails] How to change the page title of the browser for each page
How to get the id of PRIMAY KEY auto_incremented in MyBatis
I examined the concept of the process to understand how Docker works
How to solve the unknown error when using slf4j in Java
[chown] How to change the owner of a file or directory
How to check for the contents of a java fixed-length string
How to get the length of an audio file in java
Three Reasons to Frustrate Before the Release of a Web Service
I tried to solve the problem of Google Tech Dev Guide
How to increment the value of Map in one line in Java
How to use the link_to method
How to use the include? method
How to use the form_with method