掌握Java线程:Callable与Future机制详解
常见的两种创建线程的方式。一种是直接继承Thread,另外一种就是实现Runnable接口。 这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。 从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。 Future模式的核心思想是能够让主线程将原来需要同步等待的这段时间用来做其他的事情。(因为可以异步获得执行结果,所以不用一直同步等待去获得执行结果)。
这里给一个实际使用的案例代码,理论是一样的,但是编码方式有多种。 关于代码的注意点和说明,都在注释里面,由于案例比较简单,这里不再啰嗦。 -
- package com.example.springboot;
- import com.alibaba.fastjson2.JSON;
- import com.example.springboot.entity.User;
- import com.example.springboot.mapper.UserMapper;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context@SpringBootTest;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.*;
- import java.util.function.Supplier;
- // Future 机制测试
- @SpringBootTest
- public class FutureTest {
- @Autowired
- private UserMapper userMapper;
- private static ThreadPoolExecutor pool;
- static {
- pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
- }
- @Test
- public void test1() throws Exception {
- // 创建一个调用次数为2的计数工具
- CountDownLatch countDownLatch = new CountDownLatch(2);
- // 直接在异步内组装返回数据,注意List不是线程安全的,也可以采用Vector或者synchronized关键字方式
- List<User> listTmp = new CopyOnWriteArrayList<>();
- // 通过异步返回接收,因为是编码依次接收,所以不存在安全问题
- List<User> listRe = new ArrayList<>();
- // 异步执行 1
- CompletableFuture<User> reStrFu1 = CompletableFuture.supplyAsync(new Supplier<User>() {
- @Override
- public User get() {
- try {
- Thread.sleep(2000);
- // 获取结果方式1,直接组装到上层方法变量中
- User user = userMapper.selectById(1);
- listTmp.add(user);
- return user;
- }catch (Exception e){
- e.printStackTrace();
- }finally {
- countDownLatch.countDown(); // 异步执行结束
- }
- return null;
- }
- }, pool);
- // 异步执行 2
- CompletableFuture<User> reStrFu2 = CompletableFuture.supplyAsync(new Supplier<User>() {
- @Override
- public User get() {
- try {
- Thread.sleep(2000);
- // 获取结果方式1,直接组装到上层方法变量中
- User user = userMapper.selectById(2);
- listTmp.add(user);
- return user;
- }catch (Exception e){
- e.printStackTrace();
- }finally {
- countDownLatch.countDown(); // 异步执行结束
- }
- return null;
- }
- }, pool);
- // 获取结果方式3,等待计数结束
- try {
- countDownLatch.await();
- } catch (Exception e) {
- e.printStackTrace();
- }
- listRe.add(reStrFu1.get());
- listRe.add(reStrFu2.get());
- System.out.println(listTmp + JSON.toJSONString(listTmp));
- System.out.println(listRe + JSON.toJSONString(listRe));
- }
- }
复制代码最后打印结果是一样的,都是两条数据的JSON。 END
|