spring boot异步方法@Async踩坑

前言

我的需求是创建一个新线程来执行一些操作,因为如果用同一个线程就会导致资源一直被占据,影响响应效率。

异步的概念

我的理解:异步即为在多辆车在多条路上行驶,同步即为多辆车在一条路上行驶。举个栗子:同步:当前如果正在学习c语言的话,那么我们按照课程安排是不应该学习c++的,只有等这个学期结束学完c语言,下个学期才能学习c++。异步:离散数学和c语言都是在本学期学习,你不必等c语言学完再学离散数学。

spring boot如何实现异步

Google搜索发现存在异步的注解。
spring boot异步方法@Async踩坑_第1张图片

How To Do @Async in Spring

spring boot异步方法@Async踩坑_第2张图片
spring boot异步方法@Async踩坑_第3张图片
spring boot异步方法@Async踩坑_第4张图片
image.png

@Async
public void asyncMethodWithVoidReturnType() {
    System.out.println("Execute method asynchronously. " 
      + Thread.currentThread().getName());
}

总结:1.开启异步支持 2.异步注解使用注意 3.异步示例

我的异步踩坑

1.未仔细阅读two limitations:Self-invocation — won't work.

测试代码如下:

public class AsyncTest {
  @Test
  public void test1() {
    System.out.println("test1的线程id为:" + Thread.currentThread().getId());
    test2();
  }
  
  @Async
  public void test2() {
    System.out.println("test2的线程id为:" + Thread.currentThread().getId());
  }
}

效果:两个都是同一个线程,并没有达到test2是独立的线程的效果
spring boot异步方法@Async踩坑_第5张图片
解决方案:将test2放到另一个class中,自我调用将不会生效。

2.必须为@Component或@Service注解才能使@Async生效

在将异步方法放到其他类:

// 第一个类
public class AsyncTest1 {
  public void test1() {
    System.out.println("test1的线程id为:" + Thread.currentThread().getId());
    // 新建一个AsyncTest2类,调用其异步方法
    AsyncTest2 asyncTest2 = new AsyncTest2();
    asyncTest2.test2();
  }
}

// 第二个类,定义异步方法
public class AsyncTest2 {
  @Async
  public void test2() {
    System.out.println("test2的线程id为:" + 
        Thread.currentThread().getId());
  }
}

But:结果不随我愿,依然是打印显示是同一线程。

解决:

Spring creates a proxy for each service and component you create using the common annotations. Only those proxies contain the wanted behavior defined by the method annotations such as the Async. So, calling those method not via the proxy but by the original naked class would not trigger those behaviors.
简言之:spring将会给用@Component和@Service的类创造代理,只有拥有代理的类才能在使用@Async时得到想要的结果。

你可能感兴趣的