千万级别的批量查询

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
package com.citydo.checkandbigdataquery.controller;


import com.citydo.checkandbigdataquery.model.Task;
import com.citydo.checkandbigdataquery.service.TaskService;
import com.citydo.checkandbigdataquery.task.TaskQuery;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;


@CrossOrigin
@RestController
public class TaskController {

    @Resource(name = "defaultThreadPool")
    private ThreadPoolTaskExecutor executor;

    @Autowired
    private TaskService taskService;

    @GetMapping("/query")
    public ResponseEntity query(){

        // 模拟10000个id
        List<Long> ids = new ArrayList<>();
        for (long i = 0; i <10000000; i++) {
            ids.add(i);
        }

        // 将ids按多少个进行拆分
        List<List<Long>> parts = Lists.partition(ids, 50);

        // 有多少份,就有多少次请求,有多少次请求就有多少个task
        List<Callable<List<Task>>> tasks = new ArrayList<>();
        for (List<Long> part : parts) {
            TaskQuery taskQuery = new TaskQuery(taskService);
            taskQuery.setIds(part);
            tasks.add(taskQuery);
        }
        // 每一个任务(线程)执行的结果都是一个future对象,这个对象的数据就是List<Task>
        List<Future<List<Task>>> futures = new ArrayList<>();
        for (Callable<List<Task>> task : tasks) {
            // 提交任务 == 注意这时候并没有触发线程执行,就绪状态
            futures.add(executor.submit(task));
        }
        // 最终要查询的任务集
        List<Task> allTasks = new ArrayList<>();
        // 遍历执行结果,准备正式执行(get)
        for (Future<List<Task>> future : futures) {
            try {
                // 查询任务超过3s的直接弃掉(cancel取消任务)
                List<Task> taskList =future.get(3000,TimeUnit.MILLISECONDS);
                if(!ObjectUtils.isEmpty(taskList)){
                    allTasks.addAll(taskList);
                }
            }catch (InterruptedException | ExecutionException | TimeoutException e){
                future.cancel(true);
            }
        }
        return ResponseEntity.ok(allTasks);
    }

    @GetMapping("/queryNot")
    public ResponseEntity queryNot(){
        // 模拟10000个id
        List<Long> ids = new ArrayList<>();
        for (long i = 0; i <10000000; i++) {
            ids.add(i);
        }
        return ResponseEntity.ok(taskService.queryByIds(ids));
    }

}

package com.citydo.checkandbigdataquery.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 */
@Configuration
public class ThreadPoolExecutorConfig {

    private int corePoolSize = 10;

    private int maxPoolSize = 30;

    private int queueCapacity = 8;

    private int keepAlive = 60;

    /**
     * 默认线程池线程池
     *
     * @return Executor
     */
    @Bean
    public ThreadPoolTaskExecutor defaultThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数目
        executor.setCorePoolSize(corePoolSize);
        //指定最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列中最大的数目
        executor.setQueueCapacity(queueCapacity);
        //线程名称前缀
        executor.setThreadNamePrefix("defaultThreadPool_"+ UUID.randomUUID().toString());
        //rejection-policy:当pool已经达到max size的时候,如何处理新任务
        //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        //对拒绝task的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //线程空闲后的最大存活时间
        executor.setKeepAliveSeconds(keepAlive);
        //加载
        executor.initialize();
        return executor;
    }

}

package com.citydo.checkandbigdataquery.service;

import com.citydo.checkandbigdataquery.model.Task;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>任务接口实现</p>
 */
@Service
public class TaskService {

    public List<Task> queryByIds(List<Long> ids){
        List<Task> tasks = new ArrayList<>();
        for (Long id : ids) {
            tasks.add(new Task(id, UUID.randomUUID().toString()));
        }
        return tasks;
    }
}

package com.citydo.checkandbigdataquery.task;


import com.citydo.checkandbigdataquery.model.Task;
import com.citydo.checkandbigdataquery.service.TaskService;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;


/**
 * <p>任务查询线程</p>
 */
@Data
public class TaskQuery implements Callable<List<Task>> {

    private List<Long> ids ;

    private TaskService taskService;

    /**
     * 注入service
     * @param taskService
     */
    public TaskQuery(TaskService taskService) {
        ids = new ArrayList<>();
        this.taskService = taskService;
    }

    /**
     * 回调查询
     * @return
     */
    @Override
    public List<Task> call(){
        return taskService.queryByIds(this.ids);
    }

}
package com.citydo.checkandbigdataquery.model;

import lombok.Data;

/**
 * @author nick
 */
@Data
public class Task {
    private Long id;
    private String name;

    public Task(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

参考:https://blog.csdn.net/Appleyk

发布了226 篇原创文章 · 获赞 515 · 访问量 69万+

猜你喜欢

转载自blog.csdn.net/qq_32447301/article/details/103690846