4

我......真的不知道如何更好地表达标题。但基本上,我所拥有的是一个线程池,所有这些线程都在忙着工作。我希望他们按照分配的顺序报告他们的结果,但同时,我想分批工作。为了说明,例子是

ExecutorService exec = Executors.newFixedThreadPool(8);

class MyCallable implements Callable<byte[]> {
    private final int threadnumber;

    MyCallable(int threadnumber){
        this.threadnumber = threadnumber;
    }

    public byte[] call() {
        //does something
    }
}
List<Callable<byte[]>> callables = new ArrayList<Callable<byte[]>>();

for(int i=1; i<=20; i++) {
    callables.add(new MyCallable(i));
}
try {
    List<Future<byte[]>> results = exec.invokeAll(callables);
    for(Future<byte[]> result: results) {
            System.out.write(result.get(), 0, result.get().length);
    }

基本上,池线程有 8 个线程,我最终有 20 个任务(这些只是示例)。如果我理解正确的话,它现在的工作方式是等到所有 20 个任务都完成后再按顺序输出它们(从 1 到 20)。这个程序应该做的是输出一个连续的字节流(由线程处理,由于我需要保持顺序不变,所以我使用了未来的接口)。虽然我不介意等到所有 20 个任务都完成后,但无论如何,线程是否可以按顺序简单地输出。

如果没有办法,或者我只是完全误解了 invokeAll 的工作原理,那么也欢迎澄清。提前致谢!执行者有点令人困惑,因为我才刚刚了解它们。

随机附录,我什至可以从可调用对象中返回字节数组吗?

4

2 回答 2

6

invokeAll()等到所有结果都计算完才返回。

使用循环并submit()一一代替,此方法立即返回带有未决结果的 Future :

...
for(int i=1; i<=20; i++) {
    results.add(exec.submit(new MyCallable(i))); 
}
try {
    for(Future<Integer> result: results) {
            System.out.write(result.get(), 0, result.get().length);
    }
}
...
于 2012-10-28T20:03:02.730 回答
2

使用 invokeAll 也可以实现。

 List<Future<byte[]>> results = exec.invokeAll(callables); 

它将返回未来的对象列表。

ThreadPoll 将以随机顺序执行任务。任务执行顺序无法控制。

未来对象

  1. 它是在 ThreadPool 中提交的任务的引用。

  2. 它有一个方法get()。它是一种阻塞调用方法。如果您调用 get() 方法,调用将等到任务完成。

如何保证Tasks提交顺序

结果顺序与可调用顺序相同。甚至线程池也会以不同的顺序执行,我们可以以相同的顺序检索。

对于前。

三项任务 1,2,3

1 & 3 --> 完成。

2 ------> 执行时间长。

调用 invokeAll 方法后,它将以相同的顺序返回 Future 列表。

任务 1:Future#get 方法返回结果,因为它已经完成

任务 2:Future#get 方法等待任务完成。

即使第三个任务完成,迭代也会等待第二个任务完成。它不会从第三个线程得到结果。

于 2014-08-15T18:39:07.960 回答