The rejection policy of the custom thread pool is posted to the MQ queue

1, Introduction

In the process of using the thread pool, we often encounter exceeding the cache queue of the thread pool and the maximum number of threads. At this time, if we use the default rejection policy, that is, throw an exception directly, then our data will be discarded and the program will stop. We don't know, because the program is executed concurrently, If you use try catch to catch exceptions and let the program continue to execute, but the rejected thread data has been discarded, today we will learn to solve this problem by customizing the rejection strategy of the thread pool, so that you can use the thread pool more flexibly.

Error message:

rejected from java.util.concurrent.ThreadPoolExecutor@41703c85[Running, pool size = 50, active threads = 50, queued tasks = 10000, completed tasks = 909]

1.1 parameter interpretation of thread pool

  • corePoolSize: the number of core threads in the thread pool
  • maximumPoolSize: the maximum number of threads allowed in the thread pool
  • keepAliveTime: when the number of existing threads is greater than corePoolSize, idle threads will be found to destroy. This parameter sets how long idle threads will be destroyed.
  • Unit: time unit
  • workQueue: work queue. If the current number of threads in the thread pool is greater than the core thread, the next task will be put into the queue
  • threadFactory: when creating threads, threads are produced through factory mode. This parameter is to set our custom thread creation factory.
  • handler: if the maximum number of threads is exceeded, the rejection policy we set will be executed

1.2 thread pool workflow

  1. When corePoolSize a task, a thread is created for each task.
  2. If the number of threads in the current thread pool is greater than the corePoolSize, the next tasks will be put into the workQueue queue set above.
  3. If the workQueue is full at this time, a temporary thread will be created when the task comes again. At this time, if we set keepAliveTime or allowCoreThreadTimeOut, the system will check the activity of the thread and destroy the thread once it times out.
  4. If the current thread in the thread pool is greater than the maximum number of threads in maximumPoolSize, the handler rejection policy we just set will be executed.

1.3 four rejection strategies of thread pool

  1. AbortPolicy: the default rejection policy. If the thread pool queue is full, the task is lost and a RejectedExecutionException exception is thrown.
  2. Discard policy: if the thread pool queue is full, the task will be directly lost without any exceptions.
  3. DiscardOldestPolicy: if the queue is full, the task that entered the queue first will be deleted to make room, and then try to join the queue.
  4. CallerRunsPolicy: if adding to the thread pool fails, the main thread will execute the task itself and will not wait for the thread in the thread pool to execute.

2, Code implementation

2.1 implementation of Runnable interface

Customize the CrmOpneTaskRunable class, implement the Runnable interface, and override the run method.

2.2 create thread pool

    private ThreadPoolExecutor threadPoolExecutor(){
        return  new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveSeconds,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(queueCapacity),
                Executors.defaultThreadFactory(),
                //TODO custom rejection policy RejectedExecutionHandler implements rejectedExecution method
                (r, executor) -> {
                    if (r instanceof CrmOpneTaskRunable) {
                        CrmOpneTaskRunable crmOpneTaskRunable = (CrmOpneTaskRunable) r;
                        //Direct printing
                        log.info("The thread pool queue is full, exceeding the maximum number of threads. The delivery queue is not available for processing...");

                        rabbitTemplate.convertAndSend("direct-rejected-policy",crmOpneTaskRunable.getX().toString());
                    }

                }
        );
    }

Customize the rejection policy by implementing the rejectedExecution method of RejectedExecutionHandler:

We can write in the form of Lambda expressions.

2.3 using thread pool

Wrap it with try catch.
Note: when we create the Runnable interface, we use a parametric construct to pass in the parameters.
Because if @ Autowired is directly used in the Runnable interface to directly inject restTemplate and CRM orderrepository, a null pointer exception will be reported when using.

 try {
    pool.execute(new CrmOpneTaskRunable(x,appId,timestamp,sign,url,restTemplate,crmOrderRepository));
  }catch (Exception e){
    log.error("Failed to open:"+e.getMessage());
  }

3, Testing

Thread pool rejection policy: Post MQ queue:

Queue consumption:

Tags: Java Multithreading thread pool

Posted on Mon, 22 Nov 2021 05:37:59 -0500 by robin105