【发布时间】:2019-10-30 20:57:09
【问题描述】:
我正在尝试以计划和非阻塞方式执行一些阻塞操作(例如 HTTP 请求)。假设我有 10 个请求,一个请求需要 3 秒,但我不想等待 3 秒,而是等待 1 秒并发送下一个请求。在所有执行完成后,我想将所有结果收集到一个列表中并返回给用户。
下面是我的场景原型(线程睡眠用作阻塞操作而不是HTTP请求)
public static List<Integer> getResults(List<Integer> inputs) throws InterruptedException, ExecutionException {
List<Integer> results = new LinkedList<Integer>();
Queue<Callable<Integer>> tasks = new LinkedList<Callable<Integer>>();
List<Future<Integer>> futures = new LinkedList<Future<Integer>>();
for (Integer input : inputs) {
Callable<Integer> task = new Callable<Integer>() {
public Integer call() throws InterruptedException {
Thread.sleep(3000);
return input + 1000;
}
};
tasks.add(task);
}
ExecutorService es = Executors.newCachedThreadPool();
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Callable<Integer> task = tasks.poll();
if (task == null) {
ses.shutdown();
es.shutdown();
return;
}
futures.add(es.submit(task));
}
}, 0, 1000, TimeUnit.MILLISECONDS);
while(true) {
if(futures.size() == inputs.size()) {
for (Future<Integer> future : futures) {
Integer result = future.get();
results.add(result);
}
return results;
}
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<Integer> results = getResults(new LinkedList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)));
System.out.println(Arrays.toString(results.toArray()));
}
我正在等待一个 while 循环,直到所有任务都返回正确的结果。但它永远不会进入中断条件,它会无限循环。每当我放置一个像记录器甚至断点这样的 I/O 操作时,它都会中断 while 循环,一切都会好起来的。
我对 Java 并发性比较陌生,并试图了解正在发生的事情以及这是否是正确的做法。我猜 I/O 操作会触发线程调度程序上的某些内容并使其检查集合的大小。
【问题讨论】:
标签: java concurrency scheduling