简单的@Async使用

@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

上一篇:Spring @Async异步方法中的线程隔离


下一篇:Spring Boot项目中@Async注解实现方法的异步调用