使用多线程优化批量导入的回显功能

来源:互联网 发布:如何成为淘宝砍价师 编辑:程序博客网 时间:2024/05/21 17:47

最近参与开发的项目有批量导入数据的功能,导入回显的过程中需要做一些校验,以确保导入数据的正确性。如果导入的数据特别多,校验规则也特别多,那么一条一条校验的时间就会很长,影响系统使用。这个时候可以使用多线程来并行校验。这里记录一下,以防忘掉。

一般要导入的每一条数据的校验都是相互独立的,那么让几条数据并行校验不会影响其他数据。基于这个思想,使用多线程优化导入。

笔者所在项目使用了SSM框架,代码实现是在service层(这里只是基于本人的工作环境而这样写,如果不是这样的环境,实现思想也是一样的。)
实现如下:
(1)新建一个ImportServiceImpl.java类,里面创建一个回显方法ehcoImportInfo()方法,和一个内部类ThreadParallel,实现Callable接口(如果没有返回值,也可以实现Runnable接口)。

public class ImportServiceImpl  {    //内部类(线程类)    private class ThreadParallel implements Callable<Object>{        //内部类无参构造方法,如果需要传递参数来启动线程,则定义相应的有参构造方法        public ThreadParallel() {        }        @Override        public Object call() throws Exception {            //具体的校验代码放在这里处理            return null;        }    //回显方法    public void ehcoImportInfo() {        //这个方法里面将调用内部类ThreadParallel     }}

(2)在这个ehcoImportInfo方法中使用这个内部类。

public void ehcoImportInfo() {        int listSize = 3000; // 导入3000条数据        // 根据导入的数据量确定启动线程的个数(根据实际情况来确定)        int threadNum = 0; // 记录线程数量        if (listSize > 0 && listSize < 100) {            threadNum = 1;        } else {            if (listSize >= 1000 && listSize <= 3000) {                threadNum = 10;            } else {                if ((listSize % 100) == 0) {                    threadNum = listSize / 100;                } else {                    threadNum = listSize / 100 + 1;                }            }        }        List<Object> subList; // 存放一个范围内的导入数据        int count =1; // 行号        // 存放所有分割的数据        Map<Integer, Object> map = new HashMap<Integer, Object>();         // 分割导入的数据         for (int i = 0; i < threadNum; i++) {            subList= new ArrayList<Object>();            for (int j = (listSize/threadNum)*(count-1); j < (listSize/threadNum)*count; j++) {                mList.add(list.get(j));            }            map.put(i, mList);            count ++;        }        // 存放线程返回值        List<Future> futureList = new ArrayList<Future>();         ExecutorService executorService = Executors.newFixedThreadPool(threadNum); // 创建线程池        // 创建线程,并启动线程(这是关键,这里面创建了内部线程类的对象,里面传的参数,根据实际情况决定,相应的内部类中也要有对应的构造方法。利用submit可以启动线程,)        for (int x = 0; x < map.size(); x++) {            futureList.add(executorService.submit(new ThreadParallel(map.get(x),(listSize/threadNum)*x + 1)));         }        executorService.shutdown(); // 关闭线程池        // 拼接提示信息        for (Future future : futureList) {            try {                System.out.println(future.get());            } catch (InterruptedException e) {                e.printStackTrace();            } catch (ExecutionException e) {                e.printStackTrace();            }        }    }

这只是大致的结构,代码并不完整,主要是理解这种思想和做法。总结一下:就是在方法中使用内部线程类,将大批量数据划分成小批量数据,然后每一个小批量数据启用一个线程并行运行,然后再汇总结果(不需要返回值的就不用处理结果了),这样可以成倍地降低校验时间。

原创粉丝点击