5 code examples of concurrent processing skills
In this paper, the author summarizes five techniques for dealing with concurrent programs, and gives code examples to make readers better understand and use these five methods
1. Catch interruptedexception error
Check the following code snippet:
The problem with the code is that it is impossible to terminate the thread while waiting for a new element in the queue, because the interrupt flag will never be restored:
1. The thread running the code was interrupted. 2. The BlockingQueue # poll() method throws an interruptedexception exception and clears the interrupt flag. 3. Loop condition in while (! Thread. Currentthread() Isinterrupted()) is true because the tag has been cleared.
To prevent this behavior, when a method is explicitly thrown (by declaring an interruptedexception) or implicitly thrown (by declaring / throwing an original exception), the interruptedexception exception is always caught and the interrupt flag is recovered.
2. Use a specific execution program to block the operation
The entire server becomes unresponsive due to a slow operation, which is usually not what developers want. Unfortunately, for RPC, response times are often unpredictable.
Suppose the server has 100 worker threads and an endpoint called 100 RPS. Internally, it makes an RPC call, which usually takes 10 milliseconds. At some point in time, the response time of this RPC becomes 2 seconds. During the peak period, the only thing the server can do is wait for these calls, while other endpoints are inaccessible.
The simplest way to solve this problem is to submit code, which turns the blocked call into a thread pool:
3. Transfer MDC value
MDC (mapped diagnostic context) is usually used to store specific values of a single task. For example, in a web application, it may store a request ID and a user ID for each request, so it becomes easier for MDC to find log records related to a single request or the entire user activity.
However, if some parts of the code are executed in a dedicated thread pool, the MDC in the thread (the thread submitting the task) will not continue to pass values. In the following example, the log on line 7 contains "requestid", while the log on line 9 does not:
This can be solved through the mdc#getcopyofcontextmap() method:
4. Change thread name
To simplify log reading and thread dump, you can customize the name of the thread. This can be done by using a threadfactory when creating the executorservice. There are many implementations of threadfactory interface in popular utility libraries:
Although forkjoinpool does not use the threadfactory interface, it also supports renaming threads:
Compare the thread dump with the default naming:
Compare with custom naming:
Imagine that there might be more than three threads.
5. Use the longadder counter
In the case of high competition, Java util. concurrent. atomic. Longadder counts instead of atomiclong / atomicinteger.
Longadder can span multiple cells and keep its value unchanged, but its value can also be increased if necessary. However, compared with the parent atomicxx, this will lead to higher throughput and memory consumption.
summary
The above is all about the five code examples of concurrency processing skills in this article. I hope it will be helpful to you. Interested friends can continue to refer to this site: detailed explanation of semaphore counting semaphore in Java Concurrent Programming, detailed explanation of methods to optimize Tomcat configuration (memory, concurrency, cache, etc.), etc. if you have any questions, you can leave a message at any time, and the editor will reply to you in time. Thank you for your support to this site!