当线程池中的任务缓存队列已满,且线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:
AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

DiscardPolicy:也是丢弃任务,但是不抛出异常。

DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

CallerRunsPolicy:由调用线程处理该任务

这种策略不会造成数据丢失,且可以减缓任务的提交速度,一般在异步任务批处理时使用

我们可以通过重写RejectedExecutionHandler来自定义一种拒绝或降级策略:

package com.example.demo;

import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.PostConstruct;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ThreadPoolTest {

    @Test
    public void threadPoolRejectedPolicyTest() {
        Student student1 = new Student("zhangsan", 23);
        Student student2 = new Student("lisi", 24);
        AsyncSaveStudentTask task1 = new AsyncSaveStudentTask(student1);
        AsyncSaveStudentTask task2 = new AsyncSaveStudentTask(student2);
        asyncTaskExecutor.execute(task1);
        asyncTaskExecutor.execute(task2);
    }

    private ThreadPoolTaskExecutor asyncTaskExecutor;

    @PostConstruct
    private void init() {
        asyncTaskExecutor = new ThreadPoolTaskExecutor();
        ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("threadName" + "%d").build();
        asyncTaskExecutor.setThreadFactory(factory);
        asyncTaskExecutor.setCorePoolSize(1);
        asyncTaskExecutor.setMaxPoolSize(1);
        asyncTaskExecutor.setAllowCoreThreadTimeOut(true);
        asyncTaskExecutor.setQueueCapacity(0);
        asyncTaskExecutor.setKeepAliveSeconds(3);
        asyncTaskExecutor.setDaemon(true);
        asyncTaskExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                log.error("转MQ处理");
                executorFailSendMQ(r);
            }
        });
        asyncTaskExecutor.initialize();
    }

    private void executorFailSendMQ(Runnable r){
        try {
            AsyncSaveStudentTask task = (AsyncSaveStudentTask) r;
            //从线程池失败中获取student对象
            Student student = task.getStudent();
            log.info("executorFailSendMQ send ={}",JSON.toJSONString(student));
            //重新发送mq
        }catch (Exception e){
            log.error("executorFailSendMQ error",e);
        }
    }

    class AsyncSaveStudentTask implements Runnable {

        private Student student;

        public AsyncSaveStudentTask(Student student) {
            this.student = student;
        }

        public Student getStudent() {
            return student;
        }

        @Override
        public void run() {
            System.out.println("AsyncSaveTask thread ={}" + Thread.currentThread().getName());
        }
    }

    @Data
    @AllArgsConstructor
    public static class Student {
        private String name;
        private int age;
    }
}

东瓜
18 声望3 粉丝