请教:如何将下面的程序code1改写成多线程的?直接实现Runnable接口,将根目录下的每一个目录建立一个线程?(但是出现了问题,就是建立的线程都是下载内容不完全就结束了。)
import java.io.IOException;
import java.text.ParseException;
import java.io.*;import com.enterprisedt.net.ftp.*;public class Crawler_Beta1 { static FileTransferClient ftpClient;

private final static int MAX_FIELDS = 20; public static void main(String[] args) 
throws IOException, FTPException, ParseException{ String host = "*.*.*.*";
String username = "anonymous";
String password = "[email protected]";

PrintStream ps = 
                     new PrintStream(new FileOutputStream(new File("E:/" + host + "_Beta1.txt")));
System.setOut(ps);

ftpClient = new FileTransferClient();

ftpClient.setRemoteHost(host);
ftpClient.setUserName(username);
ftpClient.setPassword(password);
ftpClient.getAdvancedSettings().setControlEncoding("GBK");
ftpClient.connect();
long startTime = System.currentTimeMillis();

System.out.println("目录: " + "/");
FTPFile[] rootFile = ftpClient.directoryList("/");

for(int i = 0; i < rootFile.length; i++){
done_FTP("/", rootFile[i]);
}

System.out.println("It takes: " + 
                         ((System.currentTimeMillis()-startTime)/1000) + " seconds."); 
ftpClient.disconnect();

} private static void done_FTP(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {
String fileName = ftpFile.getName();

//获得文件的属性说明,zzu_FTP显示目录标识为fields[2]=="<DIR>"
String[] fields = split(ftpFile.getRaw()); 

if(fields[2].equalsIgnoreCase("<DIR>")){
String tmpName = rootName + fileName;

System.out.println("Dir: " + tmpName);

FTPFile[] tmpFile = ftpClient.directoryList(tmpName);

for(FTPFile file : tmpFile){
done_FTP(tmpName + "/", file);
}
}else {
System.out.println("File: " + "+" + fileName);
}
}

private static void done(String rootName, FTPFile ftpFile)
throws IOException, FTPException, ParseException {

String fileName = ftpFile.getName();

//获得文件的属型说明,windows xp有9个属性
String[] fields = split(ftpFile.getRaw());         if (fields[0].charAt(0)=='d' && !fields[8].equalsIgnoreCase(".") 
                     && !fields[8].equalsIgnoreCase("..")){
                     System.out.println("目录:  " + rootName + fileName);

FTPFile[] tmpFile = ftpClient.directoryList(rootName + fileName);

for(FTPFile file : tmpFile){
done(rootName + fileName + "/", file);
}         }else if(fields[0].charAt(0)=='-'){
System.out.println("普通文件: " + rootName + fileName);
}else if(fields[0].charAt(0)=='l'){
System.out.println("链接文件: " + rootName + fileName);
}
        
}

    //该方法在com.enterprisedt.net.ftp.FTPFileParser里面,也可以将类直接继承FTPFileParser类
    protected static String[] split(String str) {
        String[] fields = new String[MAX_FIELDS];
        int pos = 0;
        StringBuffer field = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (!Character.isWhitespace(ch))
                field.append(ch);
            else {
                if (field.length()> 0) {
                    fields[pos++] = field.toString();
                    field.setLength(0);
                }
            }
        }        if (field.length() > 0) {
            fields[pos++] = field.toString();
        }
        String[] result = new String[pos];
        System.arraycopy(fields, 0, result, 0, pos);
        return result;
    }
}

解决方案 »

  1.   

    提几个意见,其中函数命名上,尽量采用 驼峰 命名规范,
    Crawler_Beta1             =========> CrawlerBeta1
    done_FTP                  ---------> doneFtp
    线程可以这样写new Thread(new Runnable() {
    //这里面写你操作FTP 对象的代码即可。
    }).start();
      

  2.   


    使用单线程的话,程序正常,能下载全部的内容。
    但是我改写成多线程后(我是将根目录下的每一个第一级子目录作为一个线程来下载。但是下载的内容就不全,往往只下载到一半多的时候,线程就退出了。也没有报线程异常。)下面是我写的多线程,代码不规范,请各位见谅呵。
    package FtpSearch.Beta3;import java.io.IOException;
    import java.text.ParseException;
    import java.io.*;import com.enterprisedt.net.ftp.*;public class Crawler_MultiThread_Beta3 implements Runnable{ FileTransferClient ftpClient;

    private final static int MAX_FIELDS = 20; String rootName = "";
    FTPFile ftpFile;
    FileWriter fw;

    public Crawler_MultiThread_Beta3(String rootName, FTPFile ftpFile, 
    FileWriter fw, FileTransferClient ftpClient)
    throws FTPException, IOException{
    this.rootName = rootName;
    this.ftpFile = ftpFile;
    this.fw = fw;
    this.ftpClient = ftpClient;
    }

    public void run() {

    try {
    done_zzuFTP(this.rootName, this.ftpFile, 
                                                     this.fw, this.ftpClient);

    this.fw.write("" + System.currentTimeMillis() );
    } catch (IOException e) {
    e.printStackTrace();
    }
    } public static void main(String[] args) 
    throws IOException, FTPException, ParseException{ String host = "*.*.*.*";
    String username = "anonymous";
    String password = "[email protected]"; FileTransferClient ftpClient1 = new FileTransferClient();

    ftpClient1.setRemoteHost(host);
    ftpClient1.setUserName(username);
    ftpClient1.setPassword(password);
    // ftpClient1.setTimeout(600000); ftpClient1.getAdvancedSettings().setControlEncoding("GBK");
    ftpClient1.connect();

    System.out.println("Start at: " + 
                                                 System.currentTimeMillis() );

    FTPFile[] rootFile = ftpClient1.directoryList("/");

    for(int i = 0; i < rootFile.length; i++){ FileWriter fw = new FileWriter(new File("E:/Test1/"
                                            + rootFile[i].getName() + "_Beta3.txt"));
    //这里我是将每一个子目录分别用一个线程下载,通过构造函数传入目录,文档的类型,文件流,
    //和建立链接的ftpClient,所有线程共用ftpClient。
    //好像也没有需要同步的操作啊,不明白哪儿错了

    new Thread(new Crawler_MultiThread_Beta3("/" +
                                                rootFile[i].getName(), rootFile[i],
                                                    fw, ftpClient1) ).start();

    }

    // ftpClient1.disconnect();

    }

    /**
     * 
     * @param rootName 获取的根目录的路径
     * @param ftpFile  该目录的文档列表
     */
    private static void done_zzuFTP(String rootName, FTPFile ftpFile, 
    FileWriter fw, FileTransferClient ftpClient){

    //获得文件的类型说明
    String[] fields = split(ftpFile.getRaw()); 

    if(fields[2].equalsIgnoreCase("<DIR>")){ try {
    fw.append("Dir: " + rootName +
                                               System.getProperty("line.separator"));
    } catch (IOException e) {
    e.printStackTrace();
    }

    FTPFile[] tmpFile;
    try {
    tmpFile = ftpClient.directoryList(rootName);
    //递归下载子目录的内容
    for(FTPFile file : tmpFile){
          done_zzuFTP(rootName + "/" +
                                                    file.getName(), file, fw, ftpClient);
    }
    } catch (FTPException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (ParseException e) {
    e.printStackTrace();
    }

    }else {
    try {
    fw.append("  File: " + "+" + 
                                                ftpFile.getName() + 
                                                System.getProperty("line.separator"));
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }
    //该方法在com.enterprisedt.net.ftp.FTPFileParser里面,也可以将类直接继承FTPFileParser类
        protected static String[] split(String str) {
            String[] fields = new String[MAX_FIELDS];
            int pos = 0;
            StringBuffer field = new StringBuffer();
            for (int i = 0; i < str.length(); i++) {
                char ch = str.charAt(i);
                if (!Character.isWhitespace(ch))
                    field.append(ch);
                else {
                    if (field.length()> 0) {
                        fields[pos++] = field.toString();
                        field.setLength(0);
                    }
                }
            }
            // pick up last field
            if (field.length() > 0) {
                fields[pos++] = field.toString();
            }
            String[] result = new String[pos];
            System.arraycopy(fields, 0, result, 0, pos);
            return result;
        }

    }
      

  3.   

    代码不全,没法测试。猜测一下,可能是你没等所有线程结束就将连接断了。
    不知道你在那做的ftpClient1.disconnect();操作?
      

  4.   


    可是我没有结束线程的操作啊。com.enterprisedt库在这个网址下载,开源的。
    http://www.enterprisedt.com/products/edtftpj/downloadlink.html其他的代码是完整的,测试的话,服务器地址需要自己建立本地或其他的地址了。
      

  5.   

    哈哈 解决了 ,妈的 ,调了两天。原来是FileWriter的缓冲没有写入文件,在fw.append()的操作后面添加fw.flush()就行。谢谢各位的讨论呵!