• Java 递归调用和非递归调用


      领导要求我跑批量报文,但是文件夹下的文件按文件修改时间的先后顺序(升序) 一个一个将报文文件放到目录B中,camel会实时扫描解析B目录下的文件,解析完后会将该文件删除,因为报文的先后顺序对业务有影响,所以要求放入B目录下的报文一次只能放一个,等到B中扫描解析完将该报文文件删除后再放入另外一个报文,因为报文有上万个,手动放回很慢,所以我写了一个java小程序自动copy放入。

      

    package com.message;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    import org.apache.commons.io.FileUtils;
    
    public class MessageTest {
        
        public static void main(String[] args) throws Exception{
            
            //String sPath = "E:/message_mm1/message_mm2/"; //源目录
            //String toPath = "E:/message_mm1/message_mm3/";//目标目录
            
            //linux 目录
            //String sPath = "/usr/local/mm_test/";//源目录
            //String toPath = "/usr/local/mm_test_20170418/";//目标目录
            String sPath = "/usr/local/message_mm/message_mm_20170416/";//源目录
            String toPath = "/usr/local/messageTest/mm/";//目标目录
            
            List<File> sourceList = getFileSort(sPath);
            System.out.println("源目录文件总数========="+sourceList.size());
    
            int sIndex = 0; //源目录文件列表开始下标
            loopCopy(sIndex,sPath, toPath,sourceList);
        }
        
        /**
         * do while循环的方式copy文件
         * @param sIndex 读取源目录文件的下标
         * @param sPath 源目录
         * @param toPath 目标目录
         * @param sourceList 源目录下文件组成的List
         */
        public static void loopCopy(int sIndex,String sPath, String toPath,List<File> sourceList){
            try {
                boolean flag = true;
                do{
                    File toFile=new File(toPath);
                    File[] toList = toFile.listFiles();
                    if(toList.length==0){
                        if(sIndex < sourceList.size()){
                            FileUtils.copyFile(new File(sPath+sourceList.get(sIndex).getName()), new File(toPath+sourceList.get(sIndex).getName()));
                            System.out.println("拷贝成功,文件名:"+sourceList.get(sIndex).getName()+"文件最后修改时间:"+sourceList.get(sIndex).lastModified());
                            Thread.sleep(50); //休眠50ms
                            sIndex++;
                        }else{
                            System.out.println("执行结束,共拷贝文件总数="+sIndex);
                            flag = false;
                        }
                    }else{
                        //目标目录文件未处理完,再休眠50ms
                        Thread.sleep(50); 
                    }
                    
                }while(flag);
            }catch (Exception e) {
                e.printStackTrace();
                System.out.println("文件拷贝异常,异常原因:"+e.getMessage());
            }
        }
        
        /**
         * 递归的方式copy文件
         * @param sIndex 读取源目录文件的下标
         * @param sPath 源目录
         * @param toPath 目标目录
         * @param sourceList 源目录下文件组成的list
         */
        public static void recursionCopy(int sIndex,String sPath, String toPath,List<File> sourceList){
            File toFile=new File(toPath);
            File[] toList = toFile.listFiles();
            //System.out.println("toList========="+toList);
            try {
                if(toList.length==0){
                    if(sIndex < sourceList.size()){
                        FileUtils.copyFile(new File(sPath+sourceList.get(sIndex).getName()), new File(toPath+sourceList.get(sIndex).getName()));
                        System.out.println("拷贝成功,文件名:"+sourceList.get(sIndex).getName()+"文件最后修改时间:"+sourceList.get(sIndex).lastModified());
                        Thread.sleep(50); //休眠50ms
                        sIndex++;
                        recursionCopy(sIndex,sPath, toPath,sourceList);
                    }else{
                        System.out.println("执行结束,共拷贝文件总数="+sIndex);
                        
                    }
                }else{
                    //目标目录文件未处理完,再休眠50ms
                    Thread.sleep(50); 
                    recursionCopy(sIndex,sPath, toPath,sourceList);
                }
                
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("文件拷贝异常,异常原因:"+e.getMessage());
            }
        }
        
        /**
         * 获取目录下所有文件(按时间升序排序)
         * 
         * @param path
         * @return
         */
        public static List<File> getFileSort(String path) {
     
            List<File> list = getFiles(path, new ArrayList<File>());
            if (list != null && list.size() > 0) {
                Collections.sort(list, new Comparator<File>() {
                    public int compare(File file, File newFile) {
                        if (file.lastModified() > newFile.lastModified()) {
                            return 1;
                        } else if (file.lastModified() == newFile.lastModified()) {
                            return 0;
                        } else {
                            return -1;
                        }
     
                    }
                });
     
            }
     
            return list;
        }
        
        /**
         * 
         * 获取目录下所有文件
         * 
         * @param realpath
         * @param files
         * @return
         */
        public static List<File> getFiles(String realpath, List<File> files) {
     
            File realFile = new File(realpath);
            if (realFile.isDirectory()) {
                File[] subfiles = realFile.listFiles();
                for (File file : subfiles) {
                    if (file.isDirectory()) {
                        getFiles(file.getAbsolutePath(), files);
                    } else {
                        files.add(file);
                    }
                }
            }
            return files;
        }
    }

    上面的代码中第一次采用递归的方式调用,即方法recursionCopy,在copy了几百个文件后,抛出 StackOverflowError 异常【堆栈溢出】,因为每当Java程序启动一个新的线程时,java虚拟机会为他分配一个栈,java栈以帧为单位保持线程运行状态;当线程调用一个方法是,jvm压入一个新的栈帧到这个线程的栈中,只要这个方法还没返回,这个栈帧就存在。如果方法的嵌套调用层次太多(如递归调用),随着java栈中的帧的增多,最终导致这个线程的栈中的所有栈帧的大小的总和大于-Xss设置的值,而产生StackOverflowError溢出异常。 
      递归调用了recursionCopy次数太多导致栈溢出,递归调用虽然方法简单,但是容易发生StackOverflowError异常,所以比较安全一点的做法就是:用循环的方式代替递归调用防止栈溢出,loopCopy()方法中采用do...while方法代替递归,具体查看上面代码

  • 相关阅读:
    jQuery tips
    WCF4.0进阶系列—第十一章 编写代码控制配置和通信 (上)
    WCF4.0进阶系列—第九章 事务支持(上)
    WCF4.0进阶系列第二章 寄宿WCF服务
    WCF4.0进阶系列第五章 在因特网环境下保护WCF服务
    [JavaScript] onkeypress and onchange event
    [JavaScript]使用jQuery定制开发自己的UI
    WCF4.0进阶系列第四章 保护企业内部的WCF服务
    WCF4.0进阶系列第六章 维护服务协定和数据协定
    WCF4.0 进阶系列第一章 WCF简介
  • 原文地址:https://www.cnblogs.com/lyftest/p/6733787.html
Copyright © 2020-2023  润新知