如何使用多線程實現數據庫查詢


第一步:搭建可以運行的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參數出傳過去了,但是報錯空指針,所以查詢失敗

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM