avatar

目录
Java中的几种异步方法

    项目中有时会遇到一些计算耗时的模块,但是我们又不想阻塞主流程,只希望这些耗时模块自己在主流程之外默默计算,或在计算运行完之后告诉我们结果就好了。这种情况下使用异步方法调用是非常适宜的。这里介绍几种常用的异步方法的使用案例;

1、Future方法

    JDK并发包里的Future代表了未来的某个结果,当我们向线程池中提交任务的时候会返回该对象,可以通过future的get()方法获得执行的结果,但是jdk1.8之前的Future有点鸡肋,并不能实现真正的异步,需要阻塞的获取结果,或者不断的轮询。

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class FutureAysnTask {

public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> futureTask = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("Future task start");
String value = longTimeTask();
System.out.println("Future task end");
return value;
}
});

try {
String value = futureTask.get(4000, TimeUnit.MILLISECONDS);
System.out.println("Future task " + value);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}

}

public static String longTimeTask() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "future task finish";
}
}
  • future的get()方法在获取线程执行结果时会阻塞当前线程,因此最好等到线程执行完毕之后再调用该方法。
  • isDone()方法是非阻塞的,可以用来判断线程是否执行完毕。该方法类似轮询;

2、CompletableFuture方法

    JDK1.8之后借助原生的CompletableFuture方法,以及lambda表达式,实现了真正的异步操作,同时也极大的简化代码逻辑;

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ComplatableFutureAsynTask {

public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);

CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
System.out.println("CompletableFuture task start");

try {
// 耗时任务
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}

return "CompletableFuture task finished";
}
}, executor);

completableFuture.thenAccept(x -> {
System.out.println(x);
});
}
}

3、Spring的@Aysn注解方法

    使用Spring中的@Async注解,使用该注解的方法,称之为异步方法。该方法在执行的时候,会放到一个专门的线程中执行,调用者无需等待该方法执行完毕,即可做其他任务;

java
1
2
3
4
5
6
7
8
9
10
11
12
@Service
public class AysnChronousService {
@Async
public Future longTimeTask() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult( "AsynChronous task finished");
}
}

    该方法必须在其他类中使用,若在本类中的其他方法上使用则不会生效。

文章作者: 海东青
文章链接: https://haohaogit.github.io/2020/04/14/Java%E4%B8%AD%E7%9A%84%E5%87%A0%E7%A7%8D%E5%BC%82%E6%AD%A5%E6%96%B9%E6%B3%95/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hexo
打赏
  • 微信
    微信
  • 支付宝
    支付宝