Java - Runnable,lambda函数和类的方法

时间:2017-10-02 10:37:39

标签: java multithreading

我是Java的新手(在大学学习但是版本2)。 现在我开发了一个从s3并行下载文件的应用程序。我已经使用ExecutorServiceRunnable以这种方式并行下载多个文件:

public class DownloaderController {
    private AmazonS3 s3Client;
    private ExecutorService fixedPool;
    private TransferManager dlManager;
    private List<MultipleFileDownload> downloads = new ArrayList<>();
    public DownloaderController() {
        checkForNewWork();
    }
    public void checkForNewWork(){
        Provider1 provider = new Provider1();
        fixedPool = Executors.newFixedThreadPool(4);
        List<Download> providedDownloadList = provider.toBeDownloaded();
            for (Download temp : providedDownloadList) {
                if (!downloadData.contains(temp)) {
                    fixedPool.submit(download.downloadCompletedHandler(s3Client));
                }
            }
        }
    }
    public void printToTextArea(String msg){
        Date now = new Date();
        if ( !DateUtils.isSameDay(this.lastLogged, now)){
            this._doLogRotate();
        }
        this.lastLogged = now;
        SimpleDateFormat ft = new SimpleDateFormat("dd/MM/yyyy H:mm:ss");
        String output = "[ " + ft.format(now) + " ] " + msg + System.getProperty("line.separator");
        Platform.runLater(() -> {
            //this is a FXML object
            statusTextArea.appendText(output);
        });
    }
}

public class Provider1 implements downloadProvider {

}

public class Download {
    abstract Runnable downloadCompletedHandler(AmazonS3 s3Client);
}

public class DownloadProvider1 extends Download {
    @Override
    public Runnable downloadCompletedHandler(AmazonS3 s3Client){
        Runnable downloadwork = () -> {
            ObjectListing list = s3Client.listObjects(this.bucket,this.getFolder());
            List<S3ObjectSummary> objects = list.getObjectSummaries();
            AtomicLong workSize = new AtomicLong(0);
            List<DeleteObjectsRequest.KeyVersion> keys = new ArrayList<>();
            objects.forEach(obj -> {
                workSize.getAndAdd(obj.getSize());
                keys.add((new DeleteObjectsRequest.KeyVersion(obj.getKey())));
            });
            MultipleFileDownload fileDownload = dlManager.downloadDirectory("myBucket","folder","outputDirectory");
            try {
                fileDownload.waitForCompletion();
            } catch (Exception e){
                printToTextArea("Exception while download from AmazonS3");
            }   
        };
        return downloadwork;
    }
}

在downloadController中,我每分钟调用一个函数,将一些Download对象添加到包含必须从s3下载的文件夹的List。添加新的下载时,它也会添加到ExecutorService池中。 Download对象返回必须执行的代码,以便从s3下载文件夹以及下载完成后该怎么做。 我的问题是,Runnable和DownloadController之间的最佳通信方式是什么?

1 个答案:

答案 0 :(得分:0)

您的代码并未完全明确目标是什么。根据我的理解,我会做到这样的事情:

public class Download {
    private AmazonS3 s3Client;
    public Download(AmazonS2 client) { s3Client = client; }
    public void run() { // perform download }
}

该类除了下载文件(cfg Separation of Concern)之外什么都不做,而且是Runnable。您可以执行executorService.submit(new Download(client)),最终将完成下载;此外,您可以在不同时调用的情况下对其进行测试。

现在,您需要一个回调方法来记录它已完成。

public class LoggingCallback {
    public void log() {
        System.out.println("finished");
    }
}

也是Runnable(该方法不一定是run())。

并且,为了确保它一个接一个地触发,也许

class OneAfterTheOther {
    private Runnable first;
    private Runnable second;
    public OneAfterTheOther(Runnable r1, Runnable r2) {
        first = r1; second = r2;
    }
    public void run() { first.run(); second.run(); }
}

如果像这样提交

Download dl = new Download(client);
Logger l = new LoggingCallback();
executorService.submit(new OneAfterTheOther(dl::run, l::log));

会做我认为你想做的事。