package com.yeejoin.amos.config;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.yeejoin.amos.HousevPVapiApplication;

@EnableAsync
@Configuration
@Primary
public class ListenerAsyncConfiguration implements AsyncConfigurer {
	
	private static final Logger logger = LogManager.getLogger(ListenerAsyncConfiguration.class);

	/**
	 * 用于@Async注解获取默认线程连接池
	 * 
	 * @return
	 */
	@Override
	public Executor getAsyncExecutor() {
		// 此类由Spring提供，org.springframework.scheduling.concurrent包下，是线程池的封装类
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		// 线程池中线程的名字前缀
		taskExecutor.setThreadNamePrefix("taskThreadPool-async-");
		// 线程池核心线程数量
		taskExecutor.setCorePoolSize(20);
		// 线程池最大线程数量
		taskExecutor.setMaxPoolSize(50);
		// 线程池空闲线程存活时间，单位秒
		taskExecutor.setKeepAliveSeconds(100);
		// 线程池拒绝策略
		taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
		// 线程池任务队容量，如果不设置则默认 Integer.MAX_VALUE，
		// 队列默认使用LinkedBlockingQueue 若queueCapacity的值 <= 0,则使用SynchronousQueue
		taskExecutor.setQueueCapacity(1000);

		// 线程池中核心线程是否允许超时，默认为false
		taskExecutor.setAllowCoreThreadTimeOut(true);

		// 线程池中的超时处理时间，单位秒，有一个对应方法为毫秒，默认为不超时
		taskExecutor.setAwaitTerminationSeconds(60);

		// 初始化线程池，不可以少，否者会抛出 线程池没有初始化
		taskExecutor.initialize();
		return taskExecutor;
	}

	/**
	 * 线程未处理异常的统一处理机制，即线程池异常处理器,简单示例
	 * 
	 * @return
	 */
	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		// 异常处理器函数接口类
		return new AsyncUncaughtExceptionHandler() {
			@Override
			public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
				logger.error("============ " + throwable.getMessage() + " ===========", throwable);
				logger.error("============ " + method.getName() + " ===========", objects);
			}
		};
	}

}
