簡體   English   中英

Java線程從靜態內部類訪問外部類

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

這建立在我之前的問題上

我的ftp服務器有10個文件,例如test1.txt,test2.txt等。 我希望能夠同時下載多個文件(最多3個)。 我正在調用downloadFilesByPattern(....)如果不對downloadFile()使用同步,則僅下載了一部分文件,而不是全部下載。 如果使用同步,則將下載所有文件,但我認為它們不是並行發生的。 問題是因為實例變量傳遞給所有線程,並且所有線程都調用該實例上的方法。

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

這是因為它們都使用相同的實例

FTPClient client

您需要為每個下載/線程創建新的FTPClientService實例,或者為每個線程創建一個FTPClient實例。 我個人更喜歡第二個變體,可以使用ThreadLocal輕松實現。

FTPClient可能不是線程安全的(無論它是什么產品?)。 您可能需要在下載之前立即創建它,或者如果需要重用它,則創建一個FTP客戶端池。

另外,我建議您稍微修改一下命名約定,因為很難區分代碼ftpclient和您自己的客戶端。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM