Java 终止并向执行人提交可催缴款项

Java 终止并向执行人提交可催缴款项,java,multithreading,future,executorservice,callable,Java,Multithreading,Future,Executorservice,Callable,这将在一个月内继续,作为我任务的一部分,我尝试使用callables从URL下载文件,并且每当发生异常时,我将尝试重新提交相同的callables,次数最多 问题是,使用当前的方法,我的程序不会在“快乐日”场景中完成所有可调用项后终止,它会永远运行(可能是因为我使用的是非守护线程?它不会在给定的时间后终止吗?) 此外,我相信当前的设计将阻止再次提交失败的可调用项,因为我正在调用executor.shutdown(),因此每当可调用项失败时,执行器将阻止向执行队列添加新的可调用项 有没有办法克服这

这将在一个月内继续,作为我任务的一部分,我尝试使用callables从URL下载文件,并且每当发生异常时,我将尝试重新提交相同的callables,次数最多

问题是,使用当前的方法,我的程序不会在“快乐日”场景中完成所有可调用项后终止,它会永远运行(可能是因为我使用的是非守护线程?它不会在给定的时间后终止吗?)

此外,我相信当前的设计将阻止再次提交失败的可调用项,因为我正在调用
executor.shutdown()
,因此每当可调用项失败时,执行器将阻止向执行队列添加新的可调用项

有没有办法克服这个问题

public class DownloadManager {

int allocatedMemory;
private final int MAX_FAILURES = 5;
private ExecutorService executor;
private CompletionService<Status> completionService;
private HashMap<String, Integer> failuresPerDownload;
private HashMap<Future<Status>, DownloadWorker> URLDownloadFuturevsDownloadWorker;

public DownloadManager() {
    allocatedMemory = 0;
    executor = Executors.newWorkStealingPool();
    completionService = new ExecutorCompletionService<Status>(executor);
    URLDownloadFuturevsDownloadWorker = new HashMap<Future<Status>, DownloadWorker>();
    failuresPerDownload = new HashMap<String, Integer>();
}

public ArrayList<Status> downloadURLs(String[] urls, int memorySize) throws Exception {
    validateURLs(urls);
    for (String url : urls) {
        failuresPerDownload.put(url, 0);
    }
    ArrayList<Status> allDownloadsStatus = new ArrayList<Status>();
    allocatedMemory = memorySize / urls.length;
    for (String url : urls) {
        DownloadWorker URLDownloader = new DownloadWorker(url, allocatedMemory);
        Future<Status> downloadStatusFuture = completionService.submit(URLDownloader);
        URLDownloadFuturevsDownloadWorker.put(downloadStatusFuture, URLDownloader);
    }
    executor.shutdown();
    Future<Status> downloadQueueHead = null;
    while (!executor.isTerminated()) {
        downloadQueueHead = completionService.take();
        try {
            Status downloadStatus = downloadQueueHead.get();
            if (downloadStatus.downloadSucceeded()) {
                allDownloadsStatus.add(downloadStatus);
                System.out.println(downloadStatus);
            } else {
                handleDownloadFailure(allDownloadsStatus, downloadStatus.getUrl());

            }
        } catch (Exception e) {
            String URL = URLDownloadFuturevsDownloadWorker.get(downloadQueueHead).getAssignedURL();
            handleDownloadFailure(allDownloadsStatus, URL);
        }
    }
    return allDownloadsStatus;
}

private void handleDownloadFailure(ArrayList<Status> allDownloadsStatus, String URL) {
    int failuresPerURL = failuresPerDownload.get(URL);
    failuresPerURL++;
    if (failuresPerURL < MAX_FAILURES) {
        failuresPerDownload.put(URL, failuresPerURL);
        // resubmit the same job
        DownloadWorker downloadJob = URLDownloadFuturevsDownloadWorker.get(URL);
        completionService.submit(downloadJob);
    } else {
        Status failedDownloadStatus = new Status(URL, false);
        allDownloadsStatus.add(failedDownloadStatus);
        System.out.println(failedDownloadStatus);
    }
  }                  
}
公共类下载管理器{
int分配内存;
私人最终int MAX_故障=5;
私人遗嘱执行人;
私人CompletionService CompletionService;
私有HashMap failuresPerDownload;
私有HashMap URLDownloadFuturevsDownloadWorker;
公共下载管理器(){
allocatedMemory=0;
executor=Executors.newWorkStealingPool();
completionService=新的执行者completionService(执行者);
URLDownloadFuturevsDownloadWorker=新HashMap();
failuresPerDownload=新建HashMap();
}
公共ArrayList downloadURLs(字符串[]URL,int-memorySize)引发异常{
验证URL;
for(字符串url:url){
failuresPerDownload.put(url,0);
}
ArrayList allDownloadsStatus=新ArrayList();
allocatedMemory=memorySize/url.length;
for(字符串url:url){
DownloadWorker URLDownloader=新的DownloadWorker(url,allocatedMemory);
Future downloadStatusFuture=completionService.submit(URLDownloader);
URLDownloadFuturevsDownloadWorker.put(下载状态未来,URLDownloader);
}
executor.shutdown();
未来下载队列头=空;
而(!executor.isTerminated()){
downloadQueueHead=completionService.take();
试一试{
Status downloadStatus=downloadQueueHead.get();
if(downloadStatus.DownloadSuccessed()){
allDownloadsStatus.add(下载状态);
System.out.println(下载状态);
}否则{
handleDownloadFailure(allDownloadsStatus,downloadStatus.getUrl());
}
}捕获(例外e){
字符串URL=URLDownloadFuturevsDownloadWorker.get(downloadQueueHead.getAssignedURL();
handleDownloadFailure(所有下载状态,URL);
}
}
返回所有下载状态;
}
private void handleDownloadFailure(ArrayList allDownloadsStatus,字符串URL){
int failuresperrl=failuresPerDownload.get(URL);
failuresPerURL++;
if(故障率PRURL<最大故障率){
failuresPerDownload.put(URL,failuresperrull);
//重新提交相同的作业
DownloadWorker downloadJob=urldowloadFutureVSDownloadWorker.get(URL);
completionService.submit(下载作业);
}否则{
Status failedDownloadStatus=新状态(URL,false);
allDownloadsStatus.add(failedDownloadStatus);
System.out.println(失败下载状态);
}
}                  
}
更新:在我将while循环的条件改为计数器而不是
之后!executor.isTerminated()
它起作用了。 为什么执行器不终止?

您需要在所有工作完成后调用并终止线程

或者,您可以在构建
ExecutorService
时提供自己的
线程工厂
,并将所有线程标记为守护进程,以便在主线程退出后它们不会使进程保持活动状态。

您需要在所有工作完成后调用并终止线程

或者,在构建
ExecutorService
时,您可以提供自己的
ThreadFactory
,并将所有线程标记为守护进程,以便在主线程退出后它们不会使进程保持活动状态。

在javadoc中,我们看到了一些示例

CompletionService<Result> ecs
         = new ExecutorCompletionService<Result>(e);
     List<Future<Result>> futures
         = new ArrayList<Future<Result>>(n);
try {
...
} finally {
         for (Future<Result> f : futures)
             f.cancel(true);
     }
CompletionService ecs
=新的ExecutorCompletionService(e);
上市期货
=新阵列列表(n);
试一试{
...
}最后{
for(未来f:未来)
f、 取消(真);
}
因此,当您需要在javadoc中停止ExecutorCompletionService时,请尝试调用cancel(true),我们看到了一些示例

CompletionService<Result> ecs
         = new ExecutorCompletionService<Result>(e);
     List<Future<Result>> futures
         = new ArrayList<Future<Result>>(n);
try {
...
} finally {
         for (Future<Result> f : futures)
             f.cancel(true);
     }
CompletionService ecs
=新的ExecutorCompletionService(e);
上市期货
=新阵列列表(n);
试一试{
...
}最后{
for(未来f:未来)
f、 取消(真);
}
因此,当您需要停止ExecutorCompletionService时,请尝试在将来调用cancel(true)

我在提交可调用项后立即调用shutdown(),但它不会终止我在提交可调用项后立即调用shutdown(),但它不会终止