我正在尝试学习如何通过执行器使用线程池。 我正在尝试打印从 1 到 10(不一定按相同顺序)10
数字的阶乘结果,以先完成者为准,然后让线程休眠 1-5 秒,这将随机选择。
这是我的可调用任务:
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 ;
}
}
这是我的主要课程:
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 次,每次输出都保持不变。
然后我通过命令提示符编译它,然后在那里运行它。输出与日食不同,但再次运行多次将在此处产生相同的输出。
为什么输出不是随机的?
提前谢谢。
更新:
感谢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 循环内而不是在循环外部声明迭代器。这意味着您始终从可迭代对象中获取第一个元素,并检查它是否已完成。如果不是,则再次循环,再次检查集合中的第一个元素。
它仅在迭代对象的当前头部完成后从集合中选择下一个项,因此您将按顺序删除项。
让我们评估代码。首先,未来存储在HashSet中。使用的 while 循环是迭代这个哈希集。现在迭代器在这个循环中启动,迭代器返回第一个元素,如果它为 false,则循环结束,进程继续(包括重新启动迭代器),这将持续到第一个元素评估的时间。 当第一个结果被评估并且所有其他结果在不同的线程中并行运行时(因为有 10 个线程)也会被评估。
当第一个结果完成()时,它被打印出来并从哈希集中取出,所以下一个迭代的哈希集将少 1 个元素,因此迭代器将从第二个元素开始。这个过程(删除done元素并初始化剩余HasSet的迭代器)将继续,直到HasSet为空(while循环的条件)
现在,此代码强制打印结果按 HashSet 存储的顺序(如上所述)(HasSet 不保证任何顺序,但插入的相同元素(无论以哪种顺序)将在 HasSet 中存储相同的顺序,并且由于每次都会以相同的顺序存储 1 到 10 个相同的数字) 对于Ex Try Under代码来理解它,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));