ThreadPoolTaskExecutor的配置问题记录

  1. 配置问题: 首先使用corePoolSize中的线程,corePoolSize满了之后对新的线程排入queueCapacity队列,queueCapacity队列达到了设置的数量后,再根据maxPoolSize的配置数量,继续创建线程(当maxPoolSize > corePoolSize)或者根据策略处理掉溢出任务等(见tt12()及tt13())

  2. 异步不生效原因之一: 当主类/service类/ExecutorConfig类添加@EnableAsync注解,异步才生效,不然任务还是同步阻塞执行(见tt02())

  3. 关于Future返回值问题: 异步方法只能设置 void/Future 两种返回值,当返回值为Future,调用main线程会阻塞直到异步方法返回AsyncResult(见tt11())







测试过程需要的类(只有两个+单元测试)
一:AysncService

@Async
@Service
//@EnableAsync
public class AysncService {

    public Future<Integer> aysncTest1(){

        System.out.println(1);
        try {
            TimeUnit.MINUTES.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 醒了");
        return new AsyncResult<>(1);
    }

    public Future<Integer> aysncTest2(){

        System.out.println(2);
        try {
            TimeUnit.MINUTES.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 醒了");
        return new AsyncResult<>(2);
    }

    public Future<Integer> aysncTest3(){

        System.out.println(3);
        try {
            TimeUnit.MINUTES.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 醒了");
        return new AsyncResult<>(3);
    }

    public Future<Integer> aysncTest4(){

        System.out.println(4);
        try {
            TimeUnit.MINUTES.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 醒了");
        return new AsyncResult<>(4);
    }

    public Future<Integer>  aysncTest5(){

        System.out.println(5);
        try {
            TimeUnit.MINUTES.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 醒了");
        return new AsyncResult<>(5);
    }

//---------------------


    public void aysncTest11(){

        System.out.println("1异步开始");
        try {
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 1醒了");

    }

    public void aysncTest12(){

        System.out.println("2异步开始");
        try {
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 2醒了");
    }

    public void aysncTest13(){

        System.out.println("3异步开始");
        try {
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 3醒了");
    }

    public void aysncTest14(){

        System.out.println("4异步开始");
        try {
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 4醒了");
    }

    public void  aysncTest15(){

        System.out.println("5异步开始");
        try {
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 5醒了");

    }
}

二:ExecutorConfig

@Configuration
@EnableAsync
public class ExecutorConfig {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);

    //总结
    //① 配置问题: 首先使用corePoolSize中的线程,corePoolSize满了之后之后对新的线程排入queueCapacity队列,queueCapacity队列达到了设置的数量后,再根据maxPoolSize的设置数据,继续创建线程(当maxPoolSize > corePoolSize)或者根据策略处理多余任务等(见tt12()及tt13())
    //② @EnableAsync注解问题: 当主类/service类/ExecutorConfig类添加@EnableAsync注解,异步才生效,不然任务还是同步阻塞执行(见tt02())
    //③ 关于Future<Integer>返回值问题: 异步方法只能设置 void/Future<T> 两种返回值,当返回值为Future<T>,调用main线程会阻塞直到异步方法返回AsyncResult(见tt11())

    private int corePoolSize= 2;//核心线程池
    private int queueCapacity = 1;//当任务超过核心线程池数,允许排在队列中的任务数
    private int maxPoolSize = 3;//当排在队列中的任务也满了,允许创建的最大线程总数
    private String namePrefix = "thread-77";//线程名字

    @Bean
    public Executor asyncServiceExecutor() {
        logger.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        // AbortPolicy:抛出RejectedExecutionException
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
}

三:单元测试方法整体代码

	@Autowired
	private AysncService aysncService;

	@Test
	public void tt11(){

		try {
			//接收Future<Integer> future 返回值会使异步失效!!! 当前main会阻塞
			Future<Integer> future1 = aysncService.aysncTest1();
			System.out.println(future1.get());

			Future<Integer> future2 = aysncService.aysncTest2();
			System.out.println(future2.get());

			Future<Integer> future3 = aysncService.aysncTest3();
			System.out.println(future3.get());

			Future<Integer> future4 = aysncService.aysncTest4();
			System.out.println(future4.get());

			Future<Integer> future5 = aysncService.aysncTest5();
			System.out.println(future5.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

	}

	@Test
	public void tt02(){

		//本方法验证当主类/service类/ExecutorConfig类不添加@EnableAsync注解时,异步不生效问题

		//结果:
		//当主类/service类/ExecutorConfig类不添加@EnableAsync注解,1 2 3 4 按顺序输出
		//当主类/service类/ExecutorConfig类添加@EnableAsync注解,1 2 3 4 异步同时输出

		aysncService.aysncTest11();
		System.out.println("1异步ok");

		aysncService.aysncTest12();
		System.out.println("2异步ok");

		aysncService.aysncTest13();
		System.out.println("3异步ok");

		aysncService.aysncTest14();
		System.out.println("4异步ok");

		try {
			Thread.currentThread().join(20000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void tt12(){

		//本方法ExectorConfig需配置为:
//		private int corePoolSize= 2;//核心线程池
//		private int queueCapacity = 1;//当任务超过核心线程池数,允许排在队列中的任务数
//		private int maxPoolSize = 3;//当排在队列中的任务也满了,允许创建的最大线程总数

		//本方法验证:CorePoolSize(2)执行两个任务,queueCapacity(1)队列中排一个任务,超出队列再由maxPoolSize(3-2)执行一个任务
		//也就是异步执行3个任务+排队1个任务


		aysncService.aysncTest11();
		System.out.println("1异步ok");

		aysncService.aysncTest12();
		System.out.println("2异步ok");

		aysncService.aysncTest13();
		System.out.println("3异步ok");

		aysncService.aysncTest14();
		System.out.println("4异步ok");

		try {
			Thread.currentThread().join(20000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void tt13(){
		//本方法验证:CorePoolSize(3)执行两个任务,queueCapacity(0)队列中无排队任务,超出队列再由maxPoolSize(4-3)执行一个任务
		//也就是异步执行4个任务+排队0个任务+超出maxPoolSize 1个任务抛出RejectedExecutionException


		//本方法ExectorConfig需配置为:
//		private int corePoolSize= 3;//核心线程池
//		private int queueCapacity = 0;//当任务超过核心线程池数,允许排在队列中的任务数
//		private int maxPoolSize = 4;//当排在队列中的任务也满了,允许创建的最大线程总数


		try {
			aysncService.aysncTest11();
			System.out.println("1异步ok");

			aysncService.aysncTest12();
			System.out.println("2异步ok");

			aysncService.aysncTest13();
			System.out.println("3异步ok");

			aysncService.aysncTest14();
			System.out.println("4异步ok");

			aysncService.aysncTest15();
			System.out.println("5异步ok");
		} catch (Exception e) {
			e.printStackTrace();
		}

		//以上有一个任务会抛出RejectedExecutionException

		try {
			Thread.currentThread().join(20000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值