Java多线程查表(封装方法 多表通用)

这篇具有很好参考价值的文章主要介绍了Java多线程查表(封装方法 多表通用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

经过多线程的学习和实践 总结了两种多线程查表方法 

两种方法都经过我的封装 某表使用时 server层加上方法sql即可

查询流程:

1 count全表条数

2 通过总条数 将全表数据分为10份

3 开辟10个线程查询limit语句(线程数可自定义)

以下方法均以mysql数据库测试 其他库同理

目录

一 线程池方法

二 @Async注解方法


一 线程池方法

controller层

int totalNum = testService.countNum(new testTable());
//重写多线程中引用的方法
List<T> threadHandle = ThreadPoolUtils.threadPool(totalNum, new ThreadTableDataQuery() {
    @Override
    public List<T> selectTableData(Integer page, Integer limit) throws Exception {
        return testService.selectTableData(page, limit);
    }
});
//lambda表达式写法
//List<T> threadHandle = ThreadPoolUtils.threadPool(totalNum, (page, limit) -> testService.selectTableData(page, limit));
//转换为list对象
List<TestTable> test= JSON.parseArray(JSON.toJSONString(threadHandle), testTable.class);

当数据量多时 JSON.parseArray和JSON.toString转换方法较慢

下篇文章我再介绍下泛型List转List对象(Json转换工具类)https://blog.csdn.net/weixin_56567361/article/details/128116842

java反射方式和强转方法比阿里巴巴fastJson方式快了40多倍

ThreadPoolUtils

import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
 * 多线程查全表通用工具类
 */

public class ThreadPoolUtils {

    /**
     * 定义十个线程
     */
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

    /**
     * 多线程查全表(通用)
     * ThreadPoolExecutor线程池方法
     *
     * @param totalNum             总条数
     * @param threadTableDataQuery 查询方法(需要新建接口类)
     * @return
     */
    public static List<T> threadPool(int totalNum, ThreadTableDataQuery threadTableDataQuery) throws Exception {
        //将ArrayList转换为线程安全的SynchronizedList
        List<T> result = Collections.synchronizedList(new ArrayList<>(NumberUtils.arrayListRightSize(totalNum)));
//        List<T> result = new CopyOnWriteArrayList<>();
        //数据量超出10 即使用线程异步处理
        if (totalNum > 10) {
            //将数据分组 分成10份 计算每份的条数
            int remainder = totalNum % 10;
            int size = remainder > 0 ? totalNum / 10 + 1 : totalNum / 10;
            CountDownLatch downLatch = new CountDownLatch(10);
            for (int i = 0; i < 10; i++) {
                int page = i * size;
                executor.submit(() -> {
                    try {
                        result.addAll(threadTableDataQuery.selectTableData(page, size));
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        downLatch.countDown();
                    }
                });
            }
            try {
                downLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            result.addAll(threadTableDataQuery.selectTableData(0, 10));
        }
        return result;
    }

}

ThreadTableDataQuery接口

import org.apache.poi.ss.formula.functions.T;

import java.util.List;


public interface ThreadTableDataQuery {

    /**
     * 线程池接口类 查询方法
     *
     * @param page
     * @param limit
     * @return
     * @throws Exception
     */
    public List<T> selectTableData(Integer page, Integer limit) throws Exception;
}

interface接口

    /**
     * 泛型查询
     *
     * @param page
     * @param limit
     * @return
     */
    public List<T> selectTableData(Integer page, Integer limit);

server层

    /**
     * 泛型查询
     *
     * @param page
     * @param limit
     * @return
     */
    public List<T> selectTableData(Integer page, Integer limit);

impl层

    /**
     * 泛型查询
     *
     * @param page
     * @param limit
     * @return
     */
    @Override
    public List<T> selectTableData(Integer page, Integer limit) {
        return testMapper.selectTableData(page,limit);
    }

mapper层

import org.apache.ibatis.annotations.Param; 

   /**
     * 泛型查询
     *
     * @param
     * @return
     */
    public List<T> selectTableData(@Param("page") Integer page, 
                                   @Param("limit") Integer limit);

xml文件

    <select id="selectTableData" parameterType="..." resultMap="...">
        select id, test, name from test_table
        <if test="page != null">limit #{page},#{limit}</if>
    </select>

二 @Async注解方法

controller层

int totalNum = testService.countNum(new testTable());
//重写多线程中引用的方法
List<T> threadAsync = ThreadPoolUtils.threadAsync(totalNum, new ThreadAsyncTableDataQuery() {
    @Override
    public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) throws Exception {
        return testService.selectTableDataAsync(page, limit);
    }
});
//lambda表达式写法
//List<T> threadAsync = ThreadPoolUtils.threadAsync(totalNum, (page, limit) -> testService.selectTableDataAsync(page, limit));
//转换为list对象
List<TestTable> test= JSON.parseArray(JSON.toJSONString(threadAsync), testTable.class);

调用方法和上面线程池方法类似

ThreadPoolUtils

import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
 * 多线程查全表通用工具类
 */
public class ThreadPoolUtils {

    /**
     * 多线程查全表(通用)
     * 注解@Async线程方法
     *
     * @param totalNum
     * @param threadAsyncTableDataQuery
     * @return
     * @throws Exception
     */
    public static List<T> threadAsync(int totalNum, ThreadAsyncTableDataQuery threadAsyncTableDataQuery) throws Exception {

        List<Future<List<T>>> list = new ArrayList<>();
        if (totalNum > 10) {
            int remainder = totalNum % 10;
            int size = remainder > 0 ? totalNum / 10 + 1 : totalNum / 10;
            for (int i = 0; i < 10; i++) {
                int page = i * size;
                Future<List<T>> pv = threadAsyncTableDataQuery.selectTableDataAsync(page, size);
                list.add(pv);
            }
        } else {
            Future<List<T>> ts = threadAsyncTableDataQuery.selectTableDataAsync(0, 10);
            list.add(ts);
        }
        return ThreadPoolUtils.taskValue(list);
    }

    /**
     * 拿取线程里的数据
     *
     * @param taskFutures
     * @return
     */
    public static List<T> taskValue(List<Future<List<T>>> taskFutures) {
        List<T> result = new ArrayList<>();
        try {
            for (Future<List<T>> future : taskFutures) {
                List<T> obj = future.get();
                if (null != obj) {
                    result.addAll(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


}

ThreadAsyncTableDataQuery接口

import org.apache.poi.ss.formula.functions.T;

import java.util.List;
import java.util.concurrent.Future;


public interface ThreadAsyncTableDataQuery {

    /**
     * 注解多线程接口类 查询方法
     *
     * @param page
     * @param limit
     * @return
     * @throws Exception
     */
    public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) throws Exception;
}

server层

    /**
     * 注解多线程泛型查询
     *
     * @param page
     * @param limit
     * @return
     */
    public Future<List<T>> selectTableDataAsync(Integer page, Integer limit);

impl层

核心注解:@Async

不加就相当于普通循环查

import org.springframework.scheduling.annotation.Async;
import java.util.concurrent.Future;
   
    /**
     * 注解多线程泛型查询
     *
     * @param page
     * @param limit
     * @return
     */
    @Async
    @Override
    public Future<List<T>> selectTableDataAsync(Integer page, Integer limit) {
        List<T> ts = testMapper.selectTableDataAsync(page,limit);
        return new AsyncResult<>(ts);
    }

mapper层 

import org.apache.ibatis.annotations.Param; 

   /**
     * 注解多线程泛型查询
     *
     * @param
     * @return
     */
    public List<T> selectTableDataAsync(@Param("page") Integer page, 
                                        @Param("limit") Integer limit);

xml文件

    <select id="selectTableDataAsync" parameterType="..." resultMap="...">
        select id, test, name from test_table
        <if test="page != null">limit #{page},#{limit}</if>
    </select>

启动程序

加上@EnableAsync注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * 启动程序
 */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableAsync
public class RuoYiApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RuoYiApplication.class, args);
}

速度测试

两种多线程方法都已介绍完 相比之下@Async更简便 容易理解些

现在上个测试图 看下速度

java多线程查询,开发合集,java,开发语言,sql,mysql,大数据

数据量约18w条
mybatis-plus耗时:3574ms
线程池方法耗时:541ms
注解多线程耗时:467ms
十次分割limit耗时:3259ms
单个sql耗时:1171ms

测试发现 两种多线程方法都比普通的sql查询快了一倍 当数据越多时 线程优势越明显 

最后 两种封装的多线程查表方法就讲到这里啦

如果写的有什么问题 或大家有什么有疑问 欢迎评论区讨论哦😇 文章来源地址https://www.toymoban.com/news/detail-654096.html

到了这里,关于Java多线程查表(封装方法 多表通用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【后端面经-Java】Java创建线程的方法简介

    目录 1. 线程的基本概念 1.1 线程 1.2 线程状态和生命周期 2. 创建线程的四种方法 2.1 继承Thread类 2.2 实现Runnable接口 2.3 实现Callable接口 2.4 使用线程池 3. 参考资料 学过操作系统的同学应该不陌生,线程是计算机中的最小调度单元,一个进程可以有多个线程,执行并发操作,提

    2024年02月09日
    浏览(40)
  • 用PHP封装一个强大且通用的cURL方法

    用PHP封装一个强大且通用的cURL方法。 用PHP封装一个强大且通用的cURL方法。 用PHP封装一个强大且通用的cURL方法。 用PHP封装一个强大且通用的cURL方法。

    2024年02月14日
    浏览(69)
  • java 获取当前线程的方法

      我们知道,线程是程序运行的基本单元,是程序中各进程之间通信的桥梁,一个线程的创建和销毁直接影响整个程序的运行效率。 我们在 Java中经常使用 Runnable接口来获取当前线程,获取线程的主要目的就是为了快速地启动进程。但是,由于 Runnable接口实现复杂,因此我们

    2024年02月01日
    浏览(48)
  • Java 进阶(8) 线程常用方法

    方法名 说明 public static void sleep(long millis) 当前线程主动休眠 millis 毫秒。 public static void yield() 当前线程主动放弃时间⽚,回到就绪状态,竞争下⼀次时间⽚。 public final void join() 允许其他线程加⼊到当前线程中。 public void setPriority(int) 线程优先级为1-10,默认为5,优先级越⾼,

    2023年04月16日
    浏览(38)
  • java复习-线程常用操作方法

    线程的主要方法都定义在 Thread类 之中,因此此处就是学习Thread中的方法。 构造方法: public Thread(Runnable target, String name) 设置名字: public final synchronized void setName(String name) 取得名字: public final String getName() 范例1:观察线程的名字 结果: 线程A 线程B Thread-0 总结: 说明开发

    2024年02月08日
    浏览(34)
  • 常用的Java线程阻塞业务方法

    在Java中常常使用到多线程处理一些业务,但是也会遇到多线程处理时带来的业务逻辑时序不对问题,例如需要等待一个业务处理完或者下一步的逻辑需要等待多线程得到的结果,下面是几种常用的方法 使用 Thread.join() 方法 对于已知的线程列表,可以遍历列表并调用每个线程

    2024年04月29日
    浏览(41)
  • Java多线程——并发和并行、实现方法

    代码演示 方式一 方式二 方式三

    2024年01月16日
    浏览(45)
  • 线程方法接收参数示例,Java的两种线程实现方式区别

    总所周知,Java实现多线程有两种方式,分别是继承Thread类和实现Runable接口,那么它们的区别是什么? 继承 Thread 类: 通过继承 Thread 类,你可以创建一个直接表示线程的类。你可以覆盖 Thread 类中的 run 方法来定义线程的逻辑。当调用 start 方法启动线程时,会执行该类中的

    2024年02月11日
    浏览(43)
  • Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors

    线程池介绍 什么是线程池 ? 线程池就是一个可以复用线程的技术。 不使用线程池的问题 : 如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。 线程池工作原理 : 例如线程池

    2023年04月16日
    浏览(48)
  • Java 多线程之自定义线程池(ThreadPool)使用方法

    线程池是一种 管理和复用线程 的机制,它包含一组预先创建的线程,用于执行各种任务。线程池的主要作用是提高多线程应用程序的性能和效率,并提供对线程的生命周期和资源的管理,包括线程的创建、销毁和复用。 本文主要讨论线程池执行器(ThreadPoolExecutor)的用法,

    2024年04月26日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包