zoukankan      html  css  js  c++  java
  • 异步线程池的使用

    合理使用异步线程开发项目能提高一个项目的并发量,减少响应时间。下面就简单介绍一下异步线程池的使用,参考博客:https://blog.csdn.net/hry2015/article/details/67640534

    spring 对@Async定义异步任务的方法有3种:

    1.最简单的异步调用,返回值为void;

    2.带参数的异步调用,异步方法可以传入参数;

    3.异常调用返回Future

    代码如下:

    package com.hry.spring.async.annotation;
    
    import java.util.concurrent.Future;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.AsyncResult;
    import org.springframework.stereotype.Component;
    
    /**
     * 异步方法调用
     * 
     * @author hry
     *
     */
    @Component
    public class AsyncDemo {
    	private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class);
    
    	/**
    	 * 最简单的异步调用,返回值为void
    	 */
    	@Async
    	public void asyncInvokeSimplest() {
    		log.info("asyncSimplest");
    	}
    
    	/**
    	 * 带参数的异步调用 异步方法可以传入参数
    	 * 
    	 * @param s
    	 */
    	@Async
    	public void asyncInvokeWithParameter(String s) {
    		log.info("asyncInvokeWithParameter, parementer={}", s);
    	}
    
    	/**
    	 * 异常调用返回Future
    	 * 
    	 * @param i
    	 * @return
    	 */
    	@Async
    	public Future<String> asyncInvokeReturnFuture(int i) {
    		log.info("asyncInvokeReturnFuture, parementer={}", i);
    		Future<String> future;
    		try {
    			Thread.sleep(1000 * 1);
    			future = new AsyncResult<String>("success:" + i);
    		} catch (InterruptedException e) {
    			future = new AsyncResult<String>("error");
    		}
    		return future;
    	}
    
    }
    

      

    spring启动配置的方式有两种:

    1.注解;

    2.XML配置文件

    我们先说注解的方式:

    @EnableAsync注解可以开启异步调用功能, public AsyncTaskExecutor taskExecutor() 方法自定义自己的线程池,线程池前缀”Anno-Executor”。如果不定义,则使用系统默认的线程池。代码如下:

    package com.hry.spring.async.annotation;
    
    import java.util.concurrent.RejectedExecutionHandler;
    import java.util.concurrent.ThreadPoolExecutor;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.core.task.AsyncTaskExecutor;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    /**
     * 通过@EnableAsync启动异步方法
     * @author hry
     * 
     */
    @SpringBootApplication
    @EnableAsync // 启动异步调用
    public class AsyncApplicationWithAnnotation {
    	private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithAnnotation.class);
    	
    	/**
    	 * 自定义异步线程池
    	 * 	如果没有这个方法,则使用默认的线程池
    	 * @return
    	 */
        @Bean
        public AsyncTaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setThreadNamePrefix("Anno-Executor");//设置线程名称的前缀
            executor.setCorePoolSize(5);//设置核心线程数
            executor.setMaxPoolSize(10);//设置最大线程数
    
            // 设置拒绝策略
            executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
    			@Override
    			public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    				// .....
    			}
    		});
            // 使用预定义的异常处理类
            // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    
            return executor;
        }
        
    	public static void main(String[] args) {
    		log.info("Start AsyncApplication.. ");
    		SpringApplication.run(AsyncApplicationWithAnnotation.class, args);
    	}
    }
    

     现在写测试类:

    package com.hry.spring.async.annotation;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import com.hry.spring.async.annotation.AsyncApplicationWithAnnotation;
    import com.hry.spring.async.annotation.AsyncDemo;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes=AsyncApplicationWithAnnotation.class)
    public class AsyncApplicationWithAnnotationTests {
    	@Autowired
    	private AsyncDemo asyncDemo;
    	
    	@Test
    	public void contextLoads() throws InterruptedException, ExecutionException {
    		asyncDemo.asyncInvokeSimplest();
    		asyncDemo.asyncInvokeWithParameter("test");
    		Future<String> future = asyncDemo.asyncInvokeReturnFuture(1000);
    		System.out.println(future.get());
    	}
    }
    

     启动测试类,结果如下:

    说明启动异步线程池成功,执行上面的3个方法分别用了3个线程。

    再说一下XML配置文件配置的方式:

    我们先创建XML配置文件:

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
        xmlns:context="http://www.springframework.org/schema/context"  
        xmlns:tx="http://www.springframework.org/schema/tx"  
        xmlns:task="http://www.springframework.org/schema/task"  
        xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
            http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"  
        default-lazy-init="false">  
        
      	<!-- 等价于 @EnableAsync, executor指定线程池 -->
      	<task:annotation-driven executor="xmlExecutor"/>
      	<!-- id指定线程池产生线程名称的前缀 -->
        <task:executor
            id="xmlExecutor"
            pool-size="3-20"
            queue-capacity="100"
    	    keep-alive="120"
            rejection-policy="CALLER_RUNS"/>
    	
    </beans>

      

    其中id表示线程名称的前缀,pool-size表示线程池的大小,“3-20”表示线程池的最大线程数为20,最小线程数为3,也可以设置成一个值,如:pool-size=5,则表示线程池的核心线程数和最大线程数相同,都是5。queue-capacity表示排队队列的长度。

    项目启动时读取xml配置文件,如下:

    package com.hry.spring.async.xml;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ImportResource;
    
    
    /**
     * 通过XML启动异步
     * @author hry
     *
     */
    @SpringBootApplication
    @ImportResource("classpath:/async/spring_async.xml")
    public class AsyncApplicationWithXML {
    	private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithXML.class);
    	
    	public static void main(String[] args) {
    		log.info("Start AsyncApplication.. ");
    		SpringApplication.run(AsyncApplicationWithXML.class, args);
    	}
    }  

    编写测试类:

    package com.hry.spring.async.xml;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
     
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes=AsyncApplicationWithXML.class)
    public class AsyncApplicationWithXMLTest {
    	@Autowired
    	private AsyncDemo asyncDemo;
    
    	@Test
    	public void contextLoads() throws InterruptedException, ExecutionException {
    		asyncDemo.asyncInvokeSimplest();
    		asyncDemo.asyncInvokeWithParameter("test");
    		Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
    		System.out.println(future.get());
    	}
    }
    

      

    测试结果如下:

    测试成功。

     

     

  • 相关阅读:
    java 寒假作业
    java 搭积木
    java 移动距离
    java 垒骰子
    java 饮料换购
    java 牌型种数
    ONOS基础教程(QuickStart with a VM)
    Java中 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念
    PM2使用基本介绍
    nodejs项目部署
  • 原文地址:https://www.cnblogs.com/gaopengfirst/p/10846179.html
Copyright © 2011-2022 走看看