java用多线程批次查询大量数据(Callable返回数据)方式

我看到有的数据库是一万条数据和八万条数据还有十几万条,几百万的数据,然后我就想拿这些数据测试一下,发现如果用java和数据库查询就连一万多条的数据查询出来就要10s左右,感觉太慢了。然后网上都说各种加索引,加索引貌似是有查询条件时在某个字段加索引比较快一些,但是毕竟是人家的库不能瞎动,再者说了,数据量偏大一点的,条件加上也还有好多数据怎么办,我想到了多线程的方式,话不多说,开始弄

多线程有好几种方式,今天说的方式比较好,实现Callable<> 这种方式能返回查询的数据,加上Future异步获取方式,查询效率大大加快

线程类:
 

package com.ThreadPoolHadel;
 
import com.sqlSource.SqlHadle;
 
import java.util.List;
import java.util.concurrent.Callable;
 
/**
 * Created by df on 2018/9/20.
 */
public class ThredQuery implements Callable<List> {
 
 
    SqlHadle sqlHadle=new SqlHadle();
 
    private String search;//查询条件 根据条件来定义该类的属性
 
    private int bindex;//当前页数
 
    private int num;//每页查询多少条
 
    private String table;//要查询的表名,也可以写死,也可以从前面传
 
    private List page;//每次分页查出来的数据
 
    public  ThredQuery(int bindex,int num,String table) {
        this.bindex=bindex;
        this.num=num;
        this.table=table;
        //分页查询数据库数据
        page=sqlHadle.queryTest11(bindex,num,table);
    }
 
    @Override
    public List call() throws Exception {
        //返回数据给Future
        return page;
    }
}


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
 
public class ThredQuery  implements Callable<List<Map<String, Object>>> {
    private Object myService;//需要通过够早方法把对应的业务service传进来 实际用的时候把类型变为对应的类型
    private String sex;//查询条件 根据条件来定义该类的属性
 
    private int bindex;//分页index
    private int num;//数量
 
    /**
     * 重新构造方法
     * @param myService
     * @param sex
     * @param bindex
     * @param num
     */
    public ThredQuery(Object myService,String sex,int bindex,int num){
        this.myService=myService;
        this.sex=sex;
        this.bindex=bindex;
        this.num=num;
    }
 
    @Override
    public List<Map<String, Object>> call() throws Exception {
        //通过service查询得到对应结果
        List<Map<String, Object>>  list  =new ArrayList<>(); //myService.queryBySex(sex,bindex,num);
 
        return list;
    }
}

调用类:

package com.service;
 
 
import com.ThreadPoolHadel.ThredQuery;
import com.sqlSource.SqlHadle;
import org.springframework.stereotype.Service;
 
import java.util.ArrayList;
 
import java.util.List;
import java.util.concurrent.*;
 
/**
 * Created by df on 2018/9/20.
 */
 
@Service
public class TheardQueryService {
 
    SqlHadle sqlHadle=new SqlHadle();
 
    public List<List> getMaxResult(String table) throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();//开始时间
        List<List> result = new ArrayList<>();//返回结果
        //查询数据库总数量
        int count = sqlHadle.count(table);
        int num = 8000;//一次查询多少条
        //需要查询的次数
        int times = count / num;
        if (count % num != 0) {
            times = times + 1;
        }
        //开始页数  连接的是orcle的数据库  封装的分页方式  我的是从1开始
        int bindex = 1;
        //Callable用于产生结果
        List<Callable<List>> tasks = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            Callable<List> qfe = new ThredQuery(bindex, num, table);
            tasks.add(qfe);
            bindex += bindex;
        }
        //定义固定长度的线程池  防止线程过多
        ExecutorService executorService = Executors.newFixedThreadPool(15);
        //Future用于获取结果
        List<Future<List>> futures=executorService.invokeAll(tasks);
        //处理线程返回结果
        if(futures!=null&&futures.size()>0){
            for (Future<List> future:futures){
             result.addAll(future.get());
            }
        }
 
        executorService.shutdown();//关闭线程池
        long end = System.currentTimeMillis();
        System.out.println("线程查询数据用时:"+(end-start)+"ms");
        return result;
    }
 
 
}



//第二种调用方法
import org.springframework.beans.factory.annotation.Autowired;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
 
public class QueryTest {
    @Autowired
    Object myService;
 
    public  List<Map<String, Object>> getMaxResult(String sex) throws Exception{
        long start = System.currentTimeMillis();
        List<Map<String, Object>> result=new ArrayList<>();//返回结果
        
        int count = 20000005;//mydao.getCount(); 通过count查到数据总量
 
        int num = 10000;//每次查询的条数
        //需要查询的次数
        int times=count / num;
        if(count%num !=0) {
            times=times+1;
        }
        //开始查询的行数
        int bindex = 0;
 
        List<Callable<List<Map<String, Object>>>> tasks = new ArrayList<Callable<List<Map<String, Object>>>>();//添加任务
        for(int i = 0; i <times ; i++){
            Callable<List<Map<String, Object>>> qfe = new ThredQuery(myService,sex,bindex, num);
            tasks.add(qfe);
            bindex=bindex+num;
        }
        //定义固定长度的线程池  防止线程过多
        ExecutorService execservice = Executors.newFixedThreadPool(15);
 
        List<Future<List<Map<String, Object>>>> futures = execservice.invokeAll(tasks);
            // 处理线程返回结果
        if (futures != null && futures.size() > 0) {
            for(Future<List<Map<String, Object>>> future : futures) {
                result.addAll(future.get());
            }
        }
        execservice.shutdown();  // 关闭线程池
 
        long end = System.currentTimeMillis();
        System.out.println("用时"+(start-end));
        
        return result;
    }
}

19600多条数据3秒内查询完,对于之前10m查询完毕,已经提高很多的效率了

80000多条数据7m就完成了

830305万的数据需要40m ,哈哈哈,也算差不多一百万的数据了,最主要的是没有卡死,好像不经过处理很容易卡死

 

5184121万的数据报GC了,那就演示到这吧,五百万的数据实在不适合这样查

最主要的是,你的数据量大的话要相应的更改调用方法里的 num,一次性多查点,效率会高很多
--------------------- 
作者:dfBeautifulLive 
来源:CSDN 
原文:https://blog.csdn.net/dfBeautifulLive/article/details/82788830 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值