Mainly in the project ( Small and medium-sized projects )
There is payment and order business ( Just handle VIP, No commodity inventory is involved ), At present, the number of users has not come up , There is no problem at present , But I thought that if the number of users becomes larger , Order concurrency increases , There may be a series of problems , Take advantage of free time , Did this demo Test related issues .

The possible problems are as follows :

Duplicate order

Gao Bingfa , Slow performance

Solution :ThreadPoolExecutor Thread pool + Queue queue

1. The first is springBoot The project framework is as follows :

2. Classes involved in business test process , as follows

BusinessThread class
package com.springboot.demo.Threads; import
org.springframework.context.annotation.Scope; import
org.springframework.stereotype.Component; @Component
@Scope("prototype")//spring Multiple cases public class BusinessThread implements Runnable{
private String acceptStr; public BusinessThread(String acceptStr) {
this.acceptStr = acceptStr; } public String getAcceptStr() { return acceptStr;
} public void setAcceptStr(String acceptStr) { this.acceptStr = acceptStr; }
@Override public void run() { // Business operation
System.out.println(" Multithreading has processed the order insertion system , order number :"+acceptStr); // Thread blocking /*try {
Thread.sleep(1000); System.out.println(" Multithreading has processed the order insertion system , order number :"+acceptStr); } catch
(InterruptedException e) { e.printStackTrace(); }*/ } }
* TestThreadPoolManager class package com.springboot.demo.Threads; import
org.springframework.beans.BeansException; import
org.springframework.beans.factory.BeanFactory; import
org.springframework.beans.factory.BeanFactoryAware; import
org.springframework.stereotype.Component; import java.util.Map; import
java.util.Queue; import java.util.concurrent.*; @Component public class
TestThreadPoolManager implements BeanFactoryAware { // Used from IOC Take objects from inside private
BeanFactory factory; // If implemented Runnable The class of is through spring of application.xml File injection , Can pass
factory.getBean() obtain , This is just a mention // Thread pool maintains the minimum number of threads private final static int
CORE_POOL_SIZE = 2; // Maximum number of threads maintained by thread pool private final static int MAX_POOL_SIZE =
10; // Thread pool maintains the idle time allowed by threads private final static int KEEP_ALIVE_TIME = 0; //
Buffer queue size used by thread pool private final static int WORK_QUEUE_SIZE = 50; @Override public
void setBeanFactory(BeanFactory beanFactory) throws BeansException { factory =
beanFactory; } /** * For orders stored in the queue , Prevent duplicate submissions , In a real scene , available redis replace Verify duplicate */ Map<String,
Object> cacheMap = new ConcurrentHashMap<>(); /** * Buffer queue of orders , When the thread pool is full , Then the order will be stored in this buffer queue
*/ Queue<Object> msgQueue = new LinkedBlockingQueue<Object>(); /** *
When the thread pool is full , Execute the following code , Put the order into the buffer queue */ final RejectedExecutionHandler handler = new
RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable
r, ThreadPoolExecutor executor) { // Add order to buffer queue msgQueue.offer(((BusinessThread)
r).getAcceptStr()); System.out.println(" The system task is too busy , Give this order to ( Scheduling thread pool ) Process one by one , order number :" +
((BusinessThread) r).getAcceptStr()); } }; /** Create thread pool */ final ThreadPoolExecutor
threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
this.handler); /** Add task to order thread pool */ public void addOrders(String orderId){
System.out.println(" This order is ready to be added to the thread pool , order number :" + orderId); // Verify whether the currently entered order already exists if
(cacheMap.get(orderId) == null) { cacheMap.put(orderId, new Object());
BusinessThread businessThread = new BusinessThread(orderId);
threadPool.execute(businessThread); } } /** * Scheduled tasks of thread pool ----> be called ( Scheduling thread pool ). This thread pool supports
The need to perform tasks regularly and periodically . */ final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(5); /** * inspect ( Scheduling thread pool ), Execute once per second , Check whether the buffer queue of the order has
Order record , Then rejoin to the thread pool */ final ScheduledFuture scheduledFuture =
scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() {
// Judge whether there are records in the buffer queue if(!msgQueue.isEmpty()){
// When the queue capacity of the thread pool is less than WORK_QUEUE_SIZE, Then start buffering the order in the queue Add to Thread pool if
(threadPool.getQueue().size() < WORK_QUEUE_SIZE) { String orderId = (String)
msgQueue.poll(); BusinessThread businessThread = new BusinessThread(orderId);
System.out.println("( Scheduling thread pool ) Order business in buffer queue , Re add to thread pool , order number :"+orderId); } } } }, 0, 1,
TimeUnit.SECONDS); /** Get message buffer queue */ public Queue<Object> getMsgQueue() { return
msgQueue; } /** Terminate order thread pool + Scheduling thread pool */ public void shutdown() {
//true Indicates if the scheduled task is executing , Abort immediately ,false Then wait for the task to end before stopping
System.out.println(" Terminate order thread pool + Scheduling thread pool :"+scheduledFuture.cancel(false));
scheduler.shutdown(); threadPool.shutdown(); } }
* TestController class package com.springboot.demo; import
com.springboot.demo.Threads.TestThreadPoolManager; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.web.bind.annotation.GetMapping; import
org.springframework.web.bind.annotation.PathVariable; import
org.springframework.web.bind.annotation.RestController; import java.util.Queue;
import java.util.UUID; /** * Created by Administrator on 2018/5/9. */
@RestController public class TestController { @Autowired TestThreadPoolManager
testThreadPoolManager; /** * Test simulation order request entrance * @param id * @return */
@GetMapping("/start/{id}") public String start(@PathVariable Long id) {
// Simulated random number String orderNo = System.currentTimeMillis() +
UUID.randomUUID().toString(); testThreadPoolManager.addOrders(orderNo); return
"Test ThreadPoolExecutor start"; } /** * Out of Service * @param id * @return */
@GetMapping("/end/{id}") public String end(@PathVariable Long id) {
testThreadPoolManager.shutdown(); Queue q =
testThreadPoolManager.getMsgQueue(); System.out.println(" Thread service turned off , There are also unprocessed messages :" +
q.size()); return "Test ThreadPoolExecutor start"; } }
3. use JMeter Simulate concurrent order request

4. result

Printed log description , The starting order is directly inserted into the system , When the thread pool is full , Then use RejectedExecutionHandler Method to add the following order to
Queue Buffer queue , use ScheduledFuture Method timing ( I'm here once a second ) inspect Queue queue , Add the order in the queue to the thread pool again , Perform the following insertion tasks .

Some logs are as follows




©2019-2020 Toolsou All rights reserved,
Solve in servlet The Chinese output in is a question mark C String function and character function in language MySQL management 35 A small coup optimization Java performance —— Concise article Seven sorting algorithms (java code ) use Ansible Batch deployment SSH Password free login to remote host according to excel generate create Build table SQL sentence Spring Source code series ( sixteen )Spring merge BeanDefinition Principle of Virtual machine installation Linux course What are the common exception classes ?