如何使用多线程实现数据库查询

第一步:搭建可以运行的springboot项目

 

 

第二步:DAO层代码如下

package com.xc.springboot.dao.mapper;

import com.xc.springboot.dao.domain.MusicInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository("musicInfoMapper")
public interface MusicInfoMapper {
        /*
    前闭后开
    取前5条数据
    select * from table_name limit 0,5
    查询第11到第15条数据
    select * from table_name limit 10,5
    limit关键字的用法:
    LIMIT [offset,] rows
    offset指定要返回的第一行的偏移量,rows第二个指定返回行的最大数目。初始行的偏移量是0(不是1)。
     */
    //分页查询的方法

    @ResultMap("BaseResultMap")
    @Select("select * from music_info limit #{index},#{num}")
    public List<MusicInfo> queryByThread(@Param(value = "index")int index, @Param(value = "num")int num);
}

 

 

 

 

第三步:pojo层代码

 

package com.xc.springboot.dao.domain;



public class MusicInfo {

    // 主键id

    private Integer id;



    // 歌手名

    private String singerName;



    // 歌曲大小

    private String musicSize;



    // 歌曲名

    private String musicName;



    /**

     * 获取 主键id music_info.id

     *

     * @return 主键id

     */

    public Integer getId() {

        return id;

    }



    /**

     * 设置 主键id music_info.id

     *

     * @param id 主键id

     */

    public void setId(Integer id) {

        this.id = id;

    }



    /**

     * 获取 歌手名 music_info.singer_name

     *

     * @return 歌手名

     */

    public String getSingerName() {

        return singerName;

    }



    /**

     * 设置 歌手名 music_info.singer_name

     *

     * @param singerName 歌手名

     */

    public void setSingerName(String singerName) {

        this.singerName = singerName == null ? null : singerName.trim();

    }



    /**

     * 获取 歌曲大小 music_info.music_size

     *

     * @return 歌曲大小

     */

    public String getMusicSize() {

        return musicSize;

    }



    /**

     * 设置 歌曲大小 music_info.music_size

     *

     * @param musicSize 歌曲大小

     */

    public void setMusicSize(String musicSize) {

        this.musicSize = musicSize == null ? null : musicSize.trim();

    }



    /**

     * 获取 歌曲名 music_info.music_name

     *

     * @return 歌曲名

     */

    public String getMusicName() {

        return musicName;

    }



    /**

     * 设置 歌曲名 music_info.music_name

     *

     * @param musicName 歌曲名

     */

    public void setMusicName(String musicName) {

        this.musicName = musicName == null ? null : musicName.trim();

    }



    @Override

    public String toString() {

        return "MusicInfo{" +

                "id=" + id +

                ", singerName=‘" + singerName + ‘\‘‘ +

                ", musicSize=‘" + musicSize + ‘\‘‘ +

                ", musicName=‘" + musicName + ‘\‘‘ +

                ‘}‘;

    }

}

 

 

 

第四步:service层代码

 

package com.xc.springboot.service.impl;



import com.xc.springboot.dao.mapper.MusicInfoMapper;

import com.xc.springboot.dao.domain.MusicInfo;

import com.xc.springboot.service.MusicInfoService;

import com.xc.springboot.util.QueryThread;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;



import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



@Service("musicInfoService")

public class MusicInfoServiceImpl implements MusicInfoService {



    @Autowired

    private MusicInfoMapper musicInfoMapper;//注入依赖



    @Override

    public void queryByThread() {

        // 数据集合大小,由调用者自己指定

        int listSize = 100;

        // 开启的线程数

        int runSize = 20;

        // 一个线程处理数据条数,如果库中有100条数据,开启20个线程,那么每一个线程执行的条数就是5条

        int count = listSize / runSize;//5

        // 创建一个线程池,数量和开启线程的数量一样

        ExecutorService executor = Executors.newFixedThreadPool(runSize);

        // 计算sql语句中每个分页查询的起始和结束数据下标

        // 循环创建线程

        //此处调用具体的查询方法

        System.out.println("开始查询");

        for (int i = 0; i < runSize; i++) {

            int index = i * count;

            int num = count;

            executor.execute(new Runnable() {

                @Override

                public void run() {

                    try {

                        //查询的结果如何保存下来,会不会存在覆盖的问题

                        System.out.println("每次查询的下标:" + index + ",条数:" + num);

                        List<MusicInfo> list = musicInfoMapper.queryByThread(index , num);

                        //这里做成写入文件的方法

                    } catch (Exception e) {

                        System.out.println("查询失败" + e);

                    }

                }

            });

        }

        // 执行完关闭线程池

        executor.shutdown();

        }

}

 

 

 

第五步:controller层代码

 

package com.xc.springboot.controller;



import com.fasterxml.jackson.databind.JsonNode;

import com.xc.springboot.dao.domain.MusicInfo;

import com.xc.springboot.service.MusicInfoService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;



import javax.servlet.http.HttpServletRequest;

import java.util.HashMap;

import java.util.List;

import java.util.Map;


@Controller

public class IndexController {

    @RequestMapping("/query1")

    @ResponseBody

    public String getInfoByThread() {

        musicInfoService.queryByThread();

        return "success";

    }

}

 

 

第六步:浏览器访问:http://localhost:8080/query1

 

最后总结:

 

1、 在具体的尝试中,遇到了一些问题

(1)      无法从匿名内部类中获取返回的结果,结果无法汇总,所以最终无法在web页面显示最后查询的结果

(2)      创建一个类实现Runnable接口,然后将该对象传入execute方法执行,发现index、num参数出传过去了,但是报错空指针,所以查询失败

 

如何使用多线程实现数据库查询

上一篇:Mysql_源码包安装详细过程


下一篇:数据库介绍(MySQL安装 体系结构、基本管理)