@Async使用
最简单的使用就是
springboot项目就直接在启动类上添加 @EnableAsync 就可以使用了
而ssm或者ssh可以在 xml配置
<!-- 支持异步方法执行 -->
<task:annotation-driven />
不过大多数的使用都会使用自定义的线程池,已防止高并发时出现OOM
使用方法也很简单,建立类
@Configuration
@EnableAsync
public class ThreadPoolConfig implements AsyncConfigurer {
private static final int CORE_POOL_SIZE = 20;
private static final int MAX_POOL_SIZE = 50;
private static final int QUEUE_CAPACITY = 200;
/**
* 给@Aysnc 配置自定义线程池
*
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
// 设置队列容量
executor.setQueueCapacity(QUEUE_CAPACITY);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
//设置线程名前缀
executor.setThreadNamePrefix("ThreadPool#Task");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
System.out.println("线程池创建了");
return threadPoolTaskExecutor;
}
}
这样就可以了 使用@Async 他就会使用这个自定义的线程池
如何验证呢,你可以在使用@Async方法里调用
System.out.println(“线程名称:” + Thread.currentThread().getName());
来查看线程名是否你在线程池定义的前缀
当然,你想使用其他自定义的线程池也是可以的,在@Async(XXXXX) 填入对应线程池的名字就可以使用了
使用@Async的注意事项
最多的失效情况应该是,在方法中调用了本类的 @Async方法,让 @Async方法没有失效,原因其实就是,@Async是spring的注解,自然使用的对象是spring里的动态代理对象,就是加注解 @Autowired 这样的使用,而你调用本类方法的使用,直接就是使用 this.xxx,进行内部调用,自然@Async就没有获取到对象
解决
要不就写在另一个类, 要不就 @Autowired 自己 ,
要不就从上下文获取 SysAuditService sysLogService=(SysAuditService) Util.getMyEnginBean(“sysAuditService”);
@Async在Hibernate的坑
在 @Async 里使用 HibernateTemplate执行sql 它会报 no session 异常 因为线程里没有 Hibernate session ,没解决方法也很简单,没有就绑一个就可以了
new Runnable() {
@Override
public void run() {
// ----------绑定session到当前线程------------
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
boolean participate = ConcurrentUtil.bindHibernateSessionToThread(sessionFactory);
// ---------你的业务---------------
<pre name="code" class="java">// ----------关闭session------------
ConcurrentUtil.closeHibernateSessionFromThread(participate, sessionFactory);
}
}
bindHibernateSessionToThread方法:
public static boolean bindHibernateSessionToThread(SessionFactory sessionFactory) {
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
return true;
} else {
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
SessionHolder sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
return false;
}
closeHibernateSessionFromThread方法
public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {
if (!participate) {
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
这样就可以了
参考:https://blog.csdn.net/zhengwei223/article/details/30506455