多线程实现分段数据处理和文件复制

使用多线程实现分段处理数据,多线程复制文件

@Slf4j
public class ThreadUtil {

    /**
     * 将数据分段使用多线程处理
     *
     * @param dataList           源数据
     * @param threadSize         每几条数据创建一个线程
     * @param threadTaskFunction 函数式接口,里面是具体处理细节
     * @return
     * @throws Exception
     */
    public static List<Map<String, String>> getThreadTask(List<String> dataList, Integer threadSize, ThreadTaskFunction threadTaskFunction) throws Exception {
        List<String> threadDataList = new ArrayList<>();
        List<Map<String, String>> resultList = new ArrayList<>();
        List<Callable<List<Map<String, String>>>> taskList = new ArrayList<>();
        Callable<List<Map<String, String>>> task = null;
        //源数据大小
        int dataSize = dataList.size();
        //计算需的线程数量
        int threadNum = getThreadNum(dataSize, threadSize);
        //创建指定线程数的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
        //根据所需的线程数量划分每个线程要处理的数据
        for (int i = 0; i < threadNum; i++) {
            //若threadNum所需的线程数量为1,则使用一个线程处理所有数据
            if (i == threadNum - 1) {
                threadDataList = dataList.subList(i * threadSize, dataSize);
            } else {
                //为每个线程划分处理的数据区间,
                // 比如:[0 * threadSize,(0 + 1) * threadSize],若 threadSize= 2,
                // 第一个线程  --->[0,2]
                // 第二个线程  --->[2,4]
                System.out.println("i = " + i);
                int endIndex = (i + 1) * threadSize;
                if (endIndex > dataSize) {
                    endIndex = dataSize;
                }
                threadDataList = dataList.subList(i * threadSize, endIndex);
            }
            List<String> finalThreadDataList = threadDataList;
            //根据划分的区间集合创建指定的任务,这里调用自定义的函数式接口设定任务
            taskList.addAll(threadTaskFunction.setThreadTaskData(finalThreadDataList));
        }
        //执行所有的线程任务,获取任务处理结果
        List<Future<List<Map<String, String>>>> futures = executorService.invokeAll(taskList);
        for (Future<List<Map<String, String>>> future : futures) {
            if (future != null) {
                resultList.addAll(future.get());
            }
        }
        //关闭线程池
        executorService.shutdown();
        return resultList;
    }

    /**
     * 多线程复制文件
     *
     * @param srcFileStr  源文件路径
     * @param destFileStr 目标文件路径
     */
    public static void copyFile(String srcFileStr, String destFileStr, int threadNum) throws Exception {
        log.info("----------多线程复制文件开始-------------");
        long start = System.currentTimeMillis();
        File srcFile = new File(srcFileStr);
        File destFile = new File(destFileStr);
        long fileSize = srcFile.length();
        if (threadNum <= 0) {
            threadNum = 10;
        }
        ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
        long avg = fileSize / threadNum / (1024 * 10) * 1024 * 10;
        List<Callable<String>> taskList = new ArrayList<>();
        Callable<String> task = null;
        for (int i = 0; i < threadNum; i++) {
            if (threadNum - 1 == i) {
                task = setThreadTask(srcFile, destFile, i * avg, fileSize);
            } else {
                task = setThreadTask(srcFile, destFile, i * avg, (i + 1) * avg);
            }
            taskList.add(task);
        }
        List<Future<String>> futures = executorService.invokeAll(taskList);
        for (Future<String> future : futures) {
            log.info(future.get());
        }
        long end = System.currentTimeMillis();
        log.info("----------多线程复制文件结束-------------");
        log.info("耗时:{} 秒", (end - start) / 1000);
        executorService.shutdown();
    }

    /**
     * 设置线程任务
     *
     * @param srcFile  源文件
     * @param destFile 目标文件
     * @param start    开始
     * @param end      结束
     * @return
     */
    private static Callable<String> setThreadTask(File srcFile, File destFile, Long start, Long end) {
        return new Callable<String>() {
            @Override
            public String call() throws Exception {
                RandomAccessFile rafRead = new RandomAccessFile(srcFile, "r");
                RandomAccessFile rafWrite = new RandomAccessFile(destFile, "rw");
                rafRead.seek(start);
                rafWrite.seek(start);
                byte[] b = new byte[1024 * 10];
                int len = 0;
                while ((len = rafRead.read(b)) != -1) {
                    rafWrite.write(b, 0, len);
                    if (rafWrite.getFilePointer() >= end) {
                        break;
                    }
                }
                rafWrite.close();
                rafRead.close();
                return Thread.currentThread().getName() + ",执行完毕!";
            }
        };
    }

    /**
     * 计算所需的线程数量
     *
     * @param dataSize
     * @param threadSize
     * @return
     */
    private static Integer getThreadNum(Integer dataSize, Integer threadSize) {
        int threadNum = 0;
        if (dataSize % threadSize == 0) {
            threadNum = dataSize / threadSize;
        } else {
            threadNum = dataSize / threadSize + 1;
        }
        return threadNum;
    }
}

自定义的函数式接口

@FunctionalInterface
public interface ThreadTaskFunction {
    List<Callable<List<Map<String, String>>>> setThreadTaskData(List<String> threadDataList);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值