为什么在使用随机和线程池时输出顺序没有改变?

Why does the order of output not getting changed when using random and threadpool?

我正在尝试了解如何通过执行器使用线程池。 我正在尝试打印从 1 到 10 的 10 数字的阶乘结果(不一定按相同的顺序),以先完成的为准,然后让线程休眠 1-5 秒,这将被选为 运行domly .

这是我的可调用任务

 class FactorialCalculator implements Callable{
    @Override
    public Integer call() throws Exception {
        int i= 1, temp = num;
        while (temp > 1){
            i = i*temp;
            temp--;
        }
        int x = ThreadLocalRandom.current().nextInt(1, 6);
        Thread.sleep(x * 1000);
        return i ;
    }

}

这是我的主要内容 class:

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService e = Executors.newFixedThreadPool(10);
        Set <Future<Integer>> set= new HashSet<Future<Integer>>();
        int totalSum = 0;
        for (int i = 1; i <= 10; i++) {
            set.add(e.submit(new FactorialCalculator(i)));
        }
        while(!set.isEmpty()) {
            Iterator<Future<Integer>> iter =  set.iterator();
            Future<Integer> fi = iter.next();
            if(fi.isDone()) {
                int temp = fi.get();
                System.out.println(temp);
                iter.remove();  
            }   
        }
   }

我运行这个程序在Eclipse上运行了10次,每次输出都一样。

然后我通过命令提示符编译它,然后 运行 它在那里。输出与 eclipse 不同,但再次 运行 多次将在此处产生相同的输出。

为什么输出没有运行domly?

提前致谢。

更新:

感谢Ben指出问题:

这是我所做的更改:

Iterator<Future<Integer>> iter =  list.iterator();
        while(!list.isEmpty()) {
            Future<Integer> fi = iter.next();
            if(fi.isDone()) {
                int temp = fi.get();
                System.out.println(temp);
                iter.remove();  
            }
            if(!list.isEmpty() && iter.hasNext() == false) {
                iter =  list.iterator();
            }
        }

我相信这是因为您是在 while 循环 内声明迭代器,而不是在其外。这意味着您总是从可迭代对象中获取第一个元素,并检查它是否完成。如果不是,则再次循环,再次检查集合中的第一个元素。

它只是在迭代的当前头部完成后才从集合中选择下一个项目,因此您要按顺序删除项目。

让我们评估代码。首先,Future 存储在 HashSet 中。使用的 while 循环是迭代此 HashSet 。现在迭代器在这个循环中启动,迭代器 returns 第一个元素并检查它是否完成 (fi.isDone()) 如果它为 false 则循环结束并且过程继续(包括重新启动迭代器)这将一直持续到第一个元素已评估的时间。 到第一个结果被评估时,所有其他结果在不同线程中并行运行(因为有 10 个线程)也被评估。

当第一个结果完成时()然后它被打印出来并且也从 HashSet 中取出,因此下一次迭代的哈希集将少 1 个元素,因此 Iterator 将从第二个元素开始。这个过程(删除完成的元素并为剩余的 HasSet 初始化迭代器)将继续直到 HasSet 为空(while 循环的条件)

现在,此代码强制按 HashSet 存储的顺序打印结果(如上所述)(HasSet 不保证任何顺序,但插入的相同元素(无论以何种顺序)将具有相同的顺序存储在 HasSet 中,因为每次喂1到10个相同的数字,每次都会按相同的顺序存储) 对于 Ex Try Below 代码来理解它,Bothe 迭代将打印相同的顺序,即使它们以不同的顺序插入。

Set<Integer> intSet = new HashSet<Integer>();

for(int i = 11 ; i <= 20 ; i++){
  intSet.add(i);

}

for(Integer integer : intSet){
  System.out.println(integer);
}

System.out.println("+++++++++++++");

intSet.clear();

for(int i = 20 ; i >= 11 ; i--){
  intSet.add(i);

}

intSet.forEach(integer -> System.out.println(integer));