completionservice:如何杀死所有线程并通过5秒返回结果?

时间:2009-07-08 09:11:39

标签: java multithreading concurrency

我在使用CompletionService时遇到了一些问题。 我的任务:对大约300个html页面并行解析,我需要等待所有结果仅持续5秒,然后 - 将结果返回到主代码。 我决定使用CompletionService + Callable。 问题是如何停止由CompletionService引起的所有线程并从那些页面返回成功解析的结果?在此代码中删除了printlines,但我可以说5秒就够了(有很好的结果,但程序等待所有线程都将完成)。我的代码执行了大约2分钟。

我的主叫代码:

Collection<Callable<HCard>> solvers = new ArrayList<Callable<HCard>>();
for (final String currentUrl : allUrls) {
    solvers.add(new Callable<HCard>() {
        public HCard call() throws ParserException {
            HCard hCard = HCardParser.parseOne(currentUrl);                      
            if (hCard != null) {
                return hCard;
            } else {
                return null;
            }
        }
    });
}
ExecutorService execService = Executors.newCachedThreadPool();
Helper helper = new Helper();
List<HCard> result = helper.solve(execService, solvers);
//then i do smth with result list

我的被叫代码:

public class Helper {
List<HCard> solve(Executor e, Collection<Callable<HCard>> solvers) throws InterruptedException {
    CompletionService<HCard> cs = new ExecutorCompletionService<HCard>(e);
    int n = solvers.size();

    Future<HCard> future = null;
    HCard hCard = null;
    ArrayList<HCard> result = new ArrayList<HCard>();

    for (Callable<HCard> s : solvers) {
        cs.submit(s);
    }
    for (int i = 0; i < n; ++i) {
        try {
            future = cs.take();
            hCard = future.get();
            if (hCard != null) {
                result.add(hCard);
            }
        } catch (ExecutionException e1) {
            future.cancel(true);
        }
    }
    return result;
}

我试图使用:

  • awaitTermination(5000,TimeUnit.MILLISECONDS)
  • future.cancel(true)
  • execService.shutdownNow()
  • future.get(5000,TimeUnit.MILLISECONDS);
  • TimeOutException:我无法获取TimeOutException。

请帮助我了解我的代码背景。
提前致谢!

2 个答案:

答案 0 :(得分:6)

您需要确保您提交的任务正确地响应中断,即他们检查Thread.isInterrupted()或被视为“可中断”。

我不确定您是否需要完成此服务。

ExecutorService service = ...

// Submit all your tasks
for (Task t : tasks) {
    service.submit(t);
}

service.shutdown();

// Wait for termination
boolean success = service.awaitTermination(5, TimeUnit.SECONDS);
if (!success) {
    // awaitTermination timed out, interrupt everyone
    service.shutdownNow();
}

此时,如果您的Task对象没有响应中断

,则无法执行任何操作

答案 1 :(得分:0)

我从未使用过CompletionService,但我确信有一个轮询(timeunit,unit)调用来进行有限的等待。然后检查null。测量等待的时间并在5秒后停止等待。大约:

public class Helper {
List<HCard> solve(Executor e, Collection<Callable<HCard>> solvers) 
throws InterruptedException {
CompletionService<HCard> cs = new ExecutorCompletionService<HCard>(e);
int n = solvers.size();

Future<HCard> future = null;
HCard hCard = null;
ArrayList<HCard> result = new ArrayList<HCard>();

for (Callable<HCard> s : solvers) {
    cs.submit(s);
}
long timeleft = 5000;
for (int i = 0; i < n; ++i) {
    if (timeleft <= 0) {
        break;
    }
    try {
        long t = System.currentTimeMillis();
        future = cs.poll(timeleft, TimeUnit.MILLISECONDS);
        timeleft -= System.currentTimeMillis() - t;
        if (future != null) {
            hCard = future.get();
            if (hCard != null) {
                result.add(hCard);
            }
        } else {
           break;
        }
    } catch (ExecutionException e1) {
        future.cancel(true);
    }
}
return result;
}

虽未经过测试。