简体   繁体   English

Java线程从静态内部类访问外部类

[英]java threads access outer class from static inner class

This builds up on my previous question . 这建立在我之前的问题上

My ftp server has 10 files, say test1.txt, test2.txt and so on. 我的ftp服务器有10个文件,例如test1.txt,test2.txt等。 I want to be able to download multiple files (max 3) at the same time. 我希望能够同时下载多个文件(最多3个)。 I am calling downloadFilesByPattern(....) If I dont use synchronized on downloadFile() then only some of the file are downloaded not all. 我正在调用downloadFilesByPattern(....)如果不对downloadFile()使用同步,则仅下载了一部分文件,而不是全部下载。 If I use synchronized, then all the files are downloaded, but I don't think they are happening in parallel. 如果使用同步,则将下载所有文件,但我认为它们不是并行发生的。 Is the issue because an instance varible is passed to all threads and a method on that instance is called by all threads. 问题是因为实例变量传递给所有线程,并且所有线程都调用该实例上的方法。

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) {
        }
    }
}
}

It's because they all use the same instance of 这是因为它们都使用相同的实例

FTPClient client

You need to either create new instance of FTPClientService for every download/thread or have an instance of FTPClient for every thread. 您需要为每个下载/线程创建新的FTPClientService实例,或者为每个线程创建一个FTPClient实例。 I personally prefer the second variant which can be easily implemented using ThreadLocal. 我个人更喜欢第二个变体,可以使用ThreadLocal轻松实现。

FTPClient is probably not thread safe (what product is it coming from anyway?). FTPClient可能不是线程安全的(无论它是什么产品?)。 You may want to create it right before download or create a pool of FTP clients if you need to reuse it. 您可能需要在下载之前立即创建它,或者如果需要重用它,则创建一个FTP客户端池。

Also, I recommend you modify your naming convention a bit as it's very hard to distinguish in the code ftpclient vs your own client. 另外,我建议您稍微修改一下命名约定,因为很难区分代码ftpclient和您自己的客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM