我想做个调用rsync向远程服务器发送错误数据的程序,调用ok,发送完毕要删除文件,并且删除掉所有空的文件夹,比如base path是d:/errorfile,它下面是精确到分钟的文件夹,放入那个时间产生的错误数据文件,比如201010011223这样的文件夹。删除空文件夹是方法deleteEmptyFolder,我如果使用线程池的话,即使调用了join,也无法等到发送结束才执行,而是一开始就执行了,如果使用常规线程的话,一切ok,请问这是什么原因?
import org.apache.commons.io.FileUtils;import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class FileSender {
    private static String[] ext = {"xml", "csv", "txt"};
    private static ExecutorService pool = Executors.newCachedThreadPool();    public static void main(String[] args) {
        if (args.length == 0 || args.length != 2) {
            print("[Error] You should input parameters as [shell file full path] [Error file directory base path]");
            return;
        }
        String shellPath = args[0];  //调用rsync进行文件发送的shell文件
        String errorBasePath = args[1];//数据文件夹的路径        deleteEmptyFolder(errorBasePath);        Collection<File> files = FileUtils.listFiles(new File(errorBasePath), ext, true);        for (File file : files) {
            try {
                sendMT(shellPath, file);
//                send(shellPath, file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }        deleteEmptyFolder(errorBasePath);        print("bye bye!");    }    /**
     * 多线程发送
     * @param shellPath
     * @param f
     * @throws InterruptedException
     */
    private static void sendMT(String shellPath, final File f) throws InterruptedException {
        print("Sending " + f.getAbsolutePath());
        final Runtime runtime = Runtime.getRuntime();
        final String cmd = "./" + shellPath + " " + f.getAbsolutePath();        Thread sendWorker = new Thread() {
            public void run() {
                Process proc = null;
                BufferedReader reader = null;
                try {
                    proc = runtime.exec(cmd);                    reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                    String line = "";
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                    }                    proc.waitFor();
                } catch (IOException e) {                    e.printStackTrace();
                } catch (InterruptedException e) {
                    print(" Exection is interrupted, the reason is as below ==================");
                    e.printStackTrace();
                }                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }                deleteFile(f);                print(" exit value = " + proc.exitValue());            }
        };        pool.submit(sendWorker);
//        sendWorker.start();
        sendWorker.join();
    }    /**
     * 删除文件
     * @param file
     */
    private static void deleteFile(File file){
        print("Deleting " + file.getAbsolutePath());
        file.delete();
    }    /**
     * 单线程发送
     * @param shellPath
     * @param f
     * @throws IOException
     */
    private static void send(String shellPath, File f) throws IOException {
        Runtime runtime = Runtime.getRuntime();
        String cmd = "./" + shellPath + " " + f.getAbsolutePath();
        Process proc = runtime.exec(cmd);
        BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = new String();
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }        try {
            proc.waitFor();
        } catch (InterruptedException e) {
            System.out.println("Exection is interrupted, the reason is as below ==================");
            e.printStackTrace();
        }        reader.close();        System.out.println("exit value = " + proc.exitValue());    }    /**
     * 删除数据文件夹下面的空文件夹
     * @param basePath
     */
    private static void deleteEmptyFolder(String basePath) {
        print(" Deleting empty directories...");
        int cnt = 0;
        File[] dirs = new File(basePath).listFiles();
        for (File dir : dirs) {
            if (dir.isDirectory() && dir.list().length == 0) {
                dir.delete();
                cnt++;
            }
        }        print(cnt + " directories are deleted");
    }    private static void print(String msg) {
        System.out.println("[FileSender]" + msg);
    }}

解决方案 »

  1.   

    既然你也要等所有线程都发送完后再做删除操作 
    那就用CountDownLatch
      

  2.   

    用文件锁试试  RandomAccessFile input = null;
    input = new RandomAccessFile(file, "rw");
    FileChannel channel = input.getChannel();
    FileLock lock = channel.tryLock();
    if (lock.isValid()) {//读文件
    lock.release();// 释放文件锁
    input.close();//关闭流
    }
      

  3.   

    这个会不会有线程同步的问题啊,如果这个线程还没处理完,然后for循环又到赋值的时候了
      

  4.   

    偶尔看到一个帖子说invokeAll就可以了,试了一下,果然简单。
      

  5.   

    写了个博客,大家可以看看http://blog.csdn.net/theoffspring/archive/2011/06/09/6534559.aspx