Java ファイル比較 7、1 つのスレッドが読み取り、1 つのスレッドが書き込みを行い、フロントエンドのプログレス バー データに戻る


実は、この書き方には少し問題があります。複数のスレッドを読み取るために 1 つのスレッドを比較するというアイデアがあり、その結果、1 つのスレッドを読み取り、比較するために 1 つのスレッドを作成することになります。結局のところ、これは書き方のアイデアです

コントローラ

package com.taiyusoft.tydms.controller;

import com.alibaba.fastjson.JSONObject;
import com.taiyusoft.tydms.entity.ResponseForm;
import com.taiyusoft.tydms.service.FileComparesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;

/***
 * @Author
 * @Param
 * @return
 **/
@RestController
@RequestMapping("/fileComparesimple")
public class FileCompareController {
    
    
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private FileComparesService fileComparesService;


        @RequestMapping("/selectfileComparesimple")
    public void fileComparesimple(String firstpath, String secondpath) {
    
    

        long time1 = System.currentTimeMillis();
        File file = new File(firstpath);
        if (file.isFile() || file.isDirectory()) {
    
    
            JSONObject list = fileComparesService.fileComparesimple(firstpath, secondpath);
        }
        long time2 = System.currentTimeMillis();
        int time = (int) ((time2 - time1) / 1000);
        System.out.println("执行了:" + time + "秒!");
    }

    /**
     * 进度条初始化   直接调用文件对比
     *
     * @return
     */
    @RequestMapping("/fileComparesinit")
    public ResponseForm fileComparesinit(String firstpath, String secondpath) {
    
    
        ResponseForm responseForm = new ResponseForm();
        Integer sum = 0;
        try {
    
    
            sum = fileComparesService.initPercentage(firstpath, secondpath);
            if (sum != 0) {
    
    
                File file1 = new File(firstpath);
                File file2 = new File(secondpath);
                if (file1.isFile() || file1.isDirectory() && file2.isFile() || file2.isDirectory()) {
    
    
                    JSONObject list = fileComparesService.fileComparesimple(firstpath, secondpath);
                    responseForm.setData(list);
                    responseForm.setCode("200");
                    responseForm.setMessage(ResponseForm.message.SUCCESS);
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
            responseForm.setCode("400");
            responseForm.setMessage(ResponseForm.message.FAIL);
        }
        return responseForm;
    }

    /**
     * 文件对比时间过长时,出现该当前文件进度条百分比
     */
    @RequestMapping("/fileComparesimplePercentage")
    public ResponseForm fileComparesimplePercentage() {
    
    
        ResponseForm responseForm = new ResponseForm();
        JSONObject jsonObject;
        try {
    
    
            jsonObject = fileComparesService.fileComparesimplePercentage();
            responseForm.setData(jsonObject);
            responseForm.setCode("200");
            responseForm.setMessage(ResponseForm.message.SUCCESS);
        } catch (Exception e) {
    
    
            responseForm.setCode("400");
            responseForm.setMessage(ResponseForm.message.FAIL);
        }

        return responseForm;
    }

    /**
     * 文件处理时间过长时,专门获取文件对比结果
     *
     * @return
     */
    @RequestMapping("/getfileCompares")
    public ResponseForm getfileCompares() {
    
    
        ResponseForm responseForm = new ResponseForm();
        JSONObject jsonObject;
        try {
    
    
            jsonObject = fileComparesService.getfileCompares();
            responseForm.setData(jsonObject);
            responseForm.setCode("200");
            responseForm.setMessage(ResponseForm.message.SUCCESS);
        } catch (Exception e) {
    
    
            responseForm.setCode("400");
            responseForm.setMessage(ResponseForm.message.FAIL);
        }
        return responseForm;
    }
}

サービス

package com.taiyusoft.tydms.service;

import com.alibaba.fastjson.JSONObject;

public interface FileComparesService {
    
    
    JSONObject fileComparesimple(String firstpath, String secondpath);

    Integer initPercentage(String firstpath, String secondpath);

    JSONObject fileComparesimplePercentage();

    JSONObject getfileCompares();
}

サービス概要

package com.taiyusoft.tydms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.taiyusoft.tydms.base.util.CompareThreadUtil;
import com.taiyusoft.tydms.base.util.ReadFile2;
import com.taiyusoft.tydms.entity.Fc;
import com.taiyusoft.tydms.service.FileComparesService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class FileComparesServiceImpl implements FileComparesService {
    
    
    private static final Logger logger = Logger.getLogger(FileComparesServiceImpl.class);
    public static String syncCurrentName1 = null; // 进度条name
    public static String percentage1 ; // 进度条百分比
    public static  Integer percentagesum1 = null; // 文件总数
    public static int countfile;//当前文件个数
    public static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();//全局静态变量
    private  List listoneNot1 = new ArrayList<Fc>(); //存放数据一缺失的数据
    private  List listoneNot2 = new ArrayList<Fc>(); //存放数据二缺失的数据
    private  List listoneNot3 = new ArrayList<Fc>(); //存放数据二缺失的数据

    public static boolean flag;
    private  Boolean[] scanStop = new Boolean[1]; // 检测停止标识


    @Override
    public JSONObject fileComparesimple(String firstpath, String secondpath) {
    
    
        long startTime = System.currentTimeMillis();
        int cpuCount = 4;

//        String dirName1 = "C:\\Users\\taiyu\\Desktop\\file2\\10w";
        String dirName1 = firstpath;
        File root1 = new File(dirName1);

        String dirName2 = secondpath;
        File root2 = new File(dirName2);

        listoneNot1 = new ArrayList<Fc>();
        listoneNot2 = new ArrayList<Fc>();
        listoneNot3 = new ArrayList<Fc>();
        scanStop[0] = true;
        List list = new ArrayList();
        list.add(dirName1);
        list.add(dirName2);

        logger.info("分配线程开始...");
        CountDownLatch latchs = new CountDownLatch(cpuCount + 1);
        ExecutorService exec = Executors.newCachedThreadPool();

        // 读取文件线程
        final ReadFile2 trFile1 = new ReadFile2(
                latchs, null, list,
                 dirName1, dirName2,scanStop);
        logger.info("读取文件线程启动...");
        exec.execute(new Thread() {
    
    
            @Override
            public void run() {
    
    
                trFile1.readFile();
            }
        });


        final CompareThreadUtil thDao = new CompareThreadUtil(
                latchs, null, list, listoneNot1,
                listoneNot2, listoneNot3, root1,
                root2, dirName1, dirName2,  trFile1,scanStop);
        for (int i = 0; i < cpuCount; i++) {
    
    
            System.out.println("检测线程" + i + " 启动...");
            final int currentID = i;
            exec.execute(new Thread() {
    
    
                @Override
                public void run() {
    
    
                    thDao.addFileLevelAfter(currentID,percentagesum1,countfile);
                }
            });
        }
        try {
    
    
            exec.shutdown();
            latchs.await();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //结束时间
        long endTime1 = System.currentTimeMillis();
        //打印
        System.out.println("对比运行时间:" + (double) (endTime1 - startTime) / 1000 + "s");
        //打印数据1缺失数据
        if (listoneNot1.size() > 0) {
    
    
            logger.info("数据1删除的文件如下");
            for (int i = 0; i < listoneNot1.size(); i++) {
    
    
                logger.info(((Fc) listoneNot1.get(0)).getPath());
            }
        } else {
    
    
            logger.info("数据1无删除的文件...");
        }

        //打印数据2缺失数据
        if (listoneNot2.size() > 0) {
    
    
            logger.info("数据2删除的文件如下");
            for (int i = 0; i < listoneNot2.size(); i++) {
    
    
                logger.info(((Fc) listoneNot2.get(i)).getPath());
            }
        } else {
    
    
            logger.info("数据2无删除文件");
        }
        //打印数据3缺失数据
        if (listoneNot3.size() > 0) {
    
    
            logger.info("两数据源之间发生修改的文件如下");
            for (int i = 0; i < listoneNot3.size(); i++) {
    
    
                logger.info(((Fc) listoneNot3.get(i)).getPath());
            }
        } else {
    
    
            logger.info("两数据源之间无发生修改的文件");
        }
        //结束时间
        long endTime = System.currentTimeMillis();
        //打印
        System.out.println("程序运行时间:" + (double) (endTime - startTime) / 1000 + "s");


        JSONObject jsonObject = new JSONObject();
        jsonObject.put("数据源1发生删除的文件",listoneNot1);
        jsonObject.put("数据源2发生删除的文件",listoneNot2);
        jsonObject.put("两数据源对比发生修改的文件",listoneNot3);
        flag=true;
        jsonObject.put("flag",flag);
        return jsonObject;
    }

    @Override
    public Integer initPercentage(String firstpath, String secondpath) {
    
    
        flag=false;
        percentagesum1=0;
        percentage1="";
        syncCurrentName1="";
        readFileInfo(new File(firstpath));
        readFileInfo(new File(secondpath));
        return percentagesum1;
    }

    @Override
    public JSONObject fileComparesimplePercentage() {
    
    
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("百分比",percentage1);
        jsonObject.put("当前进行到的文件",syncCurrentName1);
        jsonObject.put("flag",flag);//为true时可以取结果

        return jsonObject;
    }

    @Override
    public JSONObject getfileCompares() {
    
    

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("数据源1发生删除的文件",listoneNot1);
        jsonObject.put("数据源2发生删除的文件",listoneNot2);
        jsonObject.put("两数据源对比发生修改的文件",listoneNot3);
        return jsonObject;
    }


    private void readFileInfo(File root) {
    
    
        if (root.exists()) {
    
    
            if (root.isDirectory()) {
    
    
                File[] files = root.listFiles();
                if (files != null) {
    
    
                    for (int i = 0; i < files.length; i++) {
    
    

                        if (files[i].isFile()) {
    
    
                            percentagesum1++;
                        } else if (files[i].isDirectory()) {
    
    
                            readFileInfo(files[i]);
                        }
                        files[i] = null;
                    }
                }
                files = null;
            } else if (root.isFile()) {
    
    
                percentagesum1++;
            }
        }
    }

}

ファイル読み取りマルチスレッド ツール クラス

package com.taiyusoft.tydms.base.util;


import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReadFile2 {
    
    
    //    private static final Logger logger = Logger.getLogger(ReadFile.class);
    private CountDownLatch latch;
    private CyclicBarrier barrier;
    private LinkedList<File> linkedList = new LinkedList();//总


    private Lock lock = new ReentrantLock();
    private Object numberLock = new Object();
    private boolean lockboo = false;
    private List<String> list;


    private File root1;
    private File root2;
    private String dirName1;
    private String dirName2;


    private Boolean[] StopIt;


    public ReadFile2(CountDownLatch latch, CyclicBarrier barrier,
                     List list,
                     String dirName1, String dirName2,
                     Boolean[] stop

    ) {
    
    
        this.latch = latch;
        this.barrier = barrier;
        this.list = list;

        this.dirName1 = dirName1;
        this.dirName2 = dirName2;

        this.StopIt = stop;

    }


    // 读取文件信息
    public void readFile() {
    
    
        try {
    
    

            readFileInfo(new File(list.get(0)));
            readFileInfo(new File(list.get(1)));

//            logger.info("读取文件线程正常停止!");
            System.out.println("读取文件线程正常停止!");
        } catch (Exception e) {
    
    

            System.out.println("错误信息!" + e);
        } finally {
    
    
            StopIt[0] = false;
            latch.countDown();
        }
    }


    private void readFileInfo(File root) {
    
    
        if (root.exists()) {
    
    
            if (root.isDirectory()) {
    
    
                File[] files = root.listFiles();
                if (files != null) {
    
    
                    for (int i = 0; i < files.length; i++) {
    
    

                        if (files[i].isFile()) {
    
    
                            addFile(files[i]);

                        } else if (files[i].isDirectory()) {
    
    
                            readFileInfo(files[i]);
                        }
                        files[i] = null;
                    }
                }
                files = null;
            } else if (root.isFile()) {
    
    
                addFile(root);
            }
        }
    }


    private void addFile(File file) {
    
    
        lock.lock();
        try {
    
    
            linkedList.addLast(file);

        } catch (Exception e) {
    
    
            System.out.println("添加文件出错:" + e);
        } finally {
    
    
            lock.unlock();
//            try {
    
    
//                if (linkedList.size() >= 10000) {
    
    
//                    synchronized (numberLock) {
    
    
//                        lockboo = true;
//                        numberLock.wait();
//                    }
//                }
//            } catch (Exception e2) {
    
    
                logger.error("锁出错:", e2);
//                System.out.println("锁出错" + e2);
//            }
        }
    }


    public void getFileInfo(File[] file) {
    
    
        lock.lock();
        try {
    
    
            file[0] = linkedList.pollFirst();

            if (lockboo && linkedList.size() <= 1000) {
    
    
                synchronized (numberLock) {
    
    
                    lockboo = false;
                    numberLock.notify();
                }
            }
        } catch (Exception e) {
    
    
//            logger.error("获取文件出错:", e);
            System.out.println("获取文件出错:" + e);
        } finally {
    
    
            lock.unlock();
        }
    }

}

ファイルマルチスレッドツールの比較

package com.taiyusoft.tydms.base.util;


import com.taiyusoft.tydms.entity.Fc;
import com.taiyusoft.tydms.service.impl.FileComparesServiceImpl;

import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CompareThreadUtil {
    
    
    private CountDownLatch latch;
    private CyclicBarrier barrier;
    private LinkedList linkedList = new LinkedList();//总
    private LinkedList<Fc> linkedList1 = new LinkedList<Fc>();//读取路径1中的所有的文件
    private LinkedList<Fc> linkedList2 = new LinkedList<Fc>();//读取路径2中的所有的文件
    private Lock lock = new ReentrantLock();
    private List listoneNot1 = new ArrayList<Fc>(); //存放数据一缺失的数据
    private List listoneNot2 = new ArrayList<Fc>(); //存放数据二缺失的数据
    private List listoneNot3 = new ArrayList<Fc>(); //存放数据二缺失的数据

    private Object numberLock = new Object();
    private boolean lockboo = false;
    private List<String> list;


    private File root1;
    private File root2;
    private String dirName1;
    private String dirName2;


    private ReadFile2 trFile1;
    private Boolean[] StopIt;


    public CompareThreadUtil(CountDownLatch latch, CyclicBarrier barrier,
                             List list,
                             List<Fc> listoneNot1, List<Fc> listoneNot2,
                             List<Fc> listoneNot3, File root1, File root2,
                             String dirName1, String dirName2, ReadFile2 trFile1, Boolean[] stop

    ) {
    
    
        this.latch = latch;
        this.barrier = barrier;

        this.list = list;
        this.listoneNot1 = listoneNot1;
        this.listoneNot2 = listoneNot2;
        this.listoneNot3 = listoneNot3;
        this.root1 = root1;
        this.root2 = root2;
        this.dirName1 = dirName1;
        this.dirName2 = dirName2;

        this.trFile1 = trFile1;
        this.StopIt = stop;
    }


    public void addFileLevelAfter(int currentID, Integer percentagesum1, int i) {
    
    

        File[] file = new File[1];
        File f0File = null;

        lock.lock();
        try {
    
    
            while (true) {
    
    
                trFile1.getFileInfo(file);
                f0File = file[0];
                if (!StopIt[0] && f0File == null) {
    
    
                    System.out.println("线程" + currentID + " 突然停止!");
                    break;
                }
                if (f0File != null) {
    
    
                    i++;
                    NumberFormat numberFormat = NumberFormat.getNumberInstance();
                    numberFormat.setMaximumFractionDigits(2);
                    String result = numberFormat.format((float) i / (float) percentagesum1 * 100);
                    FileComparesServiceImpl.percentage1 = result + "%";
                    FileComparesServiceImpl.syncCurrentName1 = f0File.getName();
                    System.out.println("当前为检测线程" + currentID + "读取的文件为第" + i + "个文件" + "文件名为" + f0File + "   文件总数为" + percentagesum1);

                    System.out.println("此时百分比为" + FileComparesServiceImpl.percentage1);


                    if (String.valueOf(f0File).startsWith(dirName1)) {
    
    
                        File file1 = new File(f0File.toString().replace(dirName1, dirName2));
                        if (file1.exists()) {
    
    
                            if (f0File.lastModified() != file1.lastModified()) {
    
    
                                Fc fc1 = new Fc();
                                fc1.setPath(f0File.getPath());
                                fc1.setLastmodified(String.valueOf(f0File.lastModified()));
                                fc1.setMd5(Md5.getMD5File(f0File));
                                listoneNot3.add(fc1);

                            }
                        } else {
    
    
                            Fc fc = new Fc();
                            fc.setPath(f0File.getPath());
                            fc.setLastmodified(String.valueOf(f0File.lastModified()));
                            fc.setMd5(Md5.getMD5File(f0File));

                            listoneNot1.add(fc);
                        }
                    } else {
    
    
                        File file2 = new File(f0File.toString().replace(dirName2, dirName1));
                        if (file2.exists()) {
    
    
                            if (f0File.lastModified() != file2.lastModified()) {
    
    
                                Fc fc1 = new Fc();
                                fc1.setPath(f0File.getPath());
                                fc1.setLastmodified(String.valueOf(f0File.lastModified()));
                                fc1.setMd5(Md5.getMD5File(f0File));
                                listoneNot3.add(fc1);

                            }
                        } else {
    
    
                            Fc fc = new Fc();
                            fc.setPath(f0File.getPath());
                            fc.setLastmodified(String.valueOf(f0File.lastModified()));
                            fc.setMd5(Md5.getMD5File(f0File));
                            listoneNot2.add(fc);
                        }
                    }
                }

            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
            System.out.println("线程" + currentID + " 正常停止!");

        } finally {
    
    
            lock.unlock();
            latch.countDown();
        }

    }


}

コンソールの結果

検出スレッドは特定のファイルと比較される必要があります (ただし無害です)
コンソール部分のログ

結果を返す

ここに画像の説明を挿入

プログレスバーの結果

ここに画像の説明を挿入

個人的なまとめ

このファイル比較の機能は半月以上かけて書いており、
ステップ数は約
0です。まず要件を伝え、要件の難易度を軽減できるかどうかを確認します(非常に重要です)(たとえば、最初のアイデアファイル比較とは、アイデア コントラストに似たファイルを作成することですが、アイデアのファイル比較の規模は何桁ですか? どの桁が必要かわかりませんか?) 1. 最初に書くアイデアを持ち
、人に聞いても、自分で考えても、どこかのブログで読んでも、大事なのは実現するという発想です。
2. デモを作成し、アイデアを試して、それが機能するかどうかを確認します。
3. 最適化の考え方は基本的に、マルチスレッドを実装し、マルチスレッドを調整することです。
4. 関数の実行時間が満足できるかどうかを確認し、満足できない場合は 1、2、3 を繰り返します (ファイル比較の列から、元の解決策である 5 ~ 6 つの異なる解決策を書いていることもわかります) 1k ファイルと md5 値の直接比較には 100 秒かかり、20w ファイル比較の最終結果は 15 秒です (通常のノートブック))
5. 最後に、プロジェクト

おすすめ

転載: blog.csdn.net/m0_54765221/article/details/125615799
おすすめ