IT虾米网

Spring开启方法异步执行详解

qq123 2019年05月10日 编程语言 191 0

@EnableAsync

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Import(AsyncConfigurationSelector.class) 
public @interface EnableAsync { 
   Class<? extends Annotation> annotation() default Annotation.class; 
   boolean proxyTargetClass() default false; 
   AdviceMode mode() default AdviceMode.PROXY; 
   int order() default Ordered.LOWEST_PRECEDENCE; 
}

@EnableAsync注解即开启Spring对方法异步执行的能力,需要和注解@Configuration配合使用。

@Configuration 
@EnableAsync 
public class AppConfig { 
 
}

 

也可以自定义线程池

@Configuration 
@EnableAsync 
public class AppConfig implements AsyncConfigurer { 
 
    @Override 
    public Executor getAsyncExecutor() { 
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
        executor.setCorePoolSize(7); 
        executor.setMaxPoolSize(42); 
        executor.setQueueCapacity(11); 
        executor.setThreadNamePrefix("MyExecutor-"); 
        executor.initialize(); 
        return executor; 
    } 
 
    @Override 
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 
        return MyAsyncUncaughtExceptionHandler(); 
    } 
 
}

@Async

@Target({ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Async { 
   String value() default ""; 
}

 

在要异步执行的方法上使用@Async注解,下面是一个没有返回值,一个带有返回值的异步调用的示例。

@Component 
public class AsyncTask { 
 
   @Async 
   public void task1() { 
       try { 
           Thread.sleep(3000); 
       } catch (InterruptedException e) { 
           e.printStackTrace(); 
       } 
   } 
 
   @Async 
   public Future<String> task2() { 
       try { 
           Thread.sleep(3000); 
       } catch (InterruptedException e) { 
           e.printStackTrace(); 
       } 
       return new AsyncResult<String>("javastack");   
   }
}

 

测试代码

 

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class AsyncTest { 
 
   private final static Logger log = LoggerFactory.getLogger(AsyncTest.class); 
 
   @Autowired 
   private AsyncTask asyncTask; 
 
   @Test 
   public void testTask1(){ 
       log.info("start"); 
       asyncTask.task1(); 
       log.info("finish"); 
   } 
 
   @Test 
   public void testTask2()  { 
       log.info("start"); 
       Future<String> future = asyncTask.task2(); 
       while (true) { 
           if (future.isDone()) { 
               try { 
                   log.info("result is " + future.get()); 
               } catch (Exception e) { 
                   e.printStackTrace(); 
               } 
               break; 
           } 
       } 
       log.info("finish"); 
   } 
 
}

 

 

注意事项

1、使用注意

@Async只能使用到被代理的对象方法上,即代理类的入口方法处,且方法必须是public的。

2、事务处理机制

使用@Async异步注解不能和@Transaction事务注解在同一个方法上同时使用,不然事务注解将无效。

要使用事务,需要把事务注解提取到方法里面的子方法上。

发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Java 编程中关于异常处理的 10 个最佳实践详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。