线程池运行线程切面实现

656 阅读1分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

目的

在线程池提交线程实现声明周期的日志打印,包括线程任务被拒绝

思路

正常来说线程池执行线程任务是没有任何日志的,但是我们可以替换这个线程对象,就想spring 替换对象实现切面一样

代码

@Slf4j
public class RunnableExWrapper implements Runnable {
    final Runnable runnable;


    public RunnableExWrapper(Runnable runnable) {
        this.runnable = runnable;
    }

    public static RunnableExWrapper of(Runnable r) {
        return of(r);
    }

  

    public void rejectCallback(){
        Optional.ofNullable(notify).ifPresent(Notify::reject);
        log.info("线程拒绝由当前线程执行");
        this.runnable.run();
    }

    @Override
    public void run() {
        
        // 线程开始运行
        try {
            this.runnable.run();
        } catch (Exception e) {
            // 线程运行异常
        }

        // 线程运行结束

    }

}

自定义线程拒绝策略

/**
 * 自定义线程拒绝策略
 */
@Slf4j
public class AppRejectedExHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//        log.info("当前线程拒绝 ===> {}", r.toString());
        if (r instanceof RunnableExWrapper) {
            RunnableExWrapper runnableExWrapper = (RunnableExWrapper) r;
            runnableExWrapper.rejectCallback();
        }


    }
}

在spring 中注册一个线程池

public ThreadPoolTaskExecutor commonCreateThreadPool(String namePrefix, int threadNum, Integer maxNum,Integer queueCapacitySize) {
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    /**核心线程数*/
    threadPoolTaskExecutor.setCorePoolSize(threadNum);
    /**维护线程最大数量*/
    threadPoolTaskExecutor.setMaxPoolSize(Optional.ofNullable(maxNum).orElse(maxPoolSize));
    /**允许的空闲时间*/
    threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
    /**任务队列 最大线程队列应该 > max + core*/
    threadPoolTaskExecutor.setQueueCapacity(Optional.ofNullable(queueCapacitySize).orElse(queueCapacity));
    threadPoolTaskExecutor.setThreadNamePrefix(namePrefix);
    // 等待所有任务结束后再关闭线程池
    threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    //当pool已经达到max size的时候,如何处理新任务
    //自定义拒绝策略
    threadPoolTaskExecutor.setRejectedExecutionHandler(new AppRejectedExHandler());
    // 初始化线程池
    threadPoolTaskExecutor.initialize();

    return threadPoolTaskExecutor;
}



@Bean("msgExecutor")
public TaskExecutor msgExecutor() {
    return commonCreateThreadPool("msgExecutor", msgPoolCoreSize, msgPoolMaxSize, queueCapacity);
}

此时提交线程

msgExecutor.execute(RunnableExWrapper.of(() -> {
    // 线程任务
    System.out.print("ssssssssss")
});