这是建立在我的previous question上的。
我的ftp服务器有10个文件,比如test1.txt、test2.txt等等。我希望能够同时下载多个文件(最多3个)。我正在调用downloadFilesByPattern(....),如果我不在downloadFile()上使用synchronized,那么只会下载部分文件,而不是全部。如果我使用同步,那么所有的文件都会被下载,但我不认为它们是并行发生的。这是一个问题,因为实例varible被传递给所有线程,而该实例上的方法被所有线程调用。
public class FTPClientService implements IClient {
private String username;
private String password;
private String port;
private String host;
private String path;
FTPClient client = new FTPClient();
private static class DownloadTask implements Runnable {
private String name;
private String toPath;
private IClient client;
public DownloadTask(String name, String toPath, IClient client) {
this.name = name;
this.toPath = toPath;
this.client = client;
}
@Override
public void run() {
System.out.println("download = " + name);
client.downloadFile(name, toPath);
}
}
public void downloadFilesByPattern(String fileNamePattern, final String outputFilePath) {
if(!changeDirectory()){
return;
}
try {
//get a list of file names that match the pattern
String[] names = client.listNames();
ExecutorService pool = Executors.newFixedThreadPool(3);
for (String name : names) {
//check if the filename matches the pattern
Pattern pattern = Pattern.compile(fileNamePattern);
Matcher matcher = pattern.matcher(name);
if(matcher.find()){
System.out.println("Match found = " + name);
pool.submit(new DownloadTask(name, outputFilePath, this));
}else{
System.out.println("No match = " + name);
}
}
pool.shutdown();
try {
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
}
} catch (IOException ex) {
}
}
public synchronized void downloadFile(String fileName, String outputFilePath) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outputFilePath+"/"+fileName);
if(this.isFilePresent(fileName)){
//look for fileName in the path and write it to
client.retrieveFile(fileName, fos);
System.out.println("Downloading file " + fileName + " ...");
}else{
System.out.println("Could not find file " + fileName);
}
} catch (IOException ex) {
} finally {
try {
fos.close();
} catch (IOException ex) {
}
}
}
}发布于 2011-09-22 02:15:34
这是因为它们都使用相同的
FTPClient client您需要为每个下载/线程创建新的FTPClientService实例,或者为每个线程创建一个FTPClient实例。我个人更喜欢第二个变体,它可以很容易地使用ThreadLocal实现。
发布于 2011-09-22 02:21:05
FTPClient可能不是线程安全的(它到底来自什么产品?)。您可能想要在下载之前创建它,或者如果您需要重用它,可以创建一个FTP客户端池。
此外,我建议您稍微修改一下命名约定,因为在代码中很难区分ftpclient和您自己的客户端。
https://stackoverflow.com/questions/7504557
复制相似问题