为了账号安全,请及时绑定邮箱和手机立即绑定

将 Java While 循环转换为多线程循环

将 Java While 循环转换为多线程循环

交互式爱情 2023-09-06 15:55:41
我有一个列表说有登录名,基于列表内容,我正在处理其他方法,例如:while ( it.hasNext() ){   method1();}由于这些任务是独立的,我不想等待序列,所以我想并行运行它们。我做了以下操作: ExecutorService service = Executors.newFixedThreadPool(5); final List<Future<?>> futures = new ArrayList<>(); while ( it.hasNext() )    {        Future<?> future = service.submit(() -> {                  method1(it.next());           });        futures.add(future);    }但问题是,它为一个登录名执行 method1 5 次...但我想要 5 个线程独立执行 method1。我哪里做错了?爱!!
查看完整描述

3 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

您的方法不是线程安全的。
it.hasNext()在每次迭代时调用,因此您可以相信获得了预期结果,但Iterator不是线程安全的。因此,如果同时执行多个Callables,则使用迭代器会产生不可预测的结果。

使用 Thread 或 Callable 当然可以利用并行性,但在使用迭代器时需要添加显式同步。
虽然使用Callable显式同步在某种程度上很烦人。

作为替代方案,您可以使用确保线程安全的集合,例如CopyOnWriteArrayList. 例如,将原始列表包装在CopyOnWriteArrayList复制构造函数中,例如:

List<Foo> copyList = new CopyOnWriteArrayList<>(list);

或者,您也可以更简单地使用并行流,这将使您的代码变得不那么冗长,但它在幕后的线程池的可配置性较低(在某些情况下,这很重要):

list.parallelStream().forEachOrdered(this::method1);


查看完整回答
反对 回复 2023-09-06
?
杨__羊羊

TA贡献1943条经验 获得超7个赞

首先尝试获取迭代值。


final <class> nextItem = it.next();

Future<?> future = service.submit(() -> { method1(nextItem); });

futures.add(future);


查看完整回答
反对 回复 2023-09-06
?
LEATH

TA贡献1936条经验 获得超7个赞

我哪里做错了?

你有一个线程正在执行此操作:

while ( it.hasNext() ) {
    Future<?> future = service.submit(...task...);
    futures.add(future);
}

该线程不断调用it.hasNext(),但它从不调用it.next()

您还有其他线程(线程池的工作线程)在调用,it.next()但这些线程独立于循环运行。如果循环向执行器服务提交任务并将 future 添加到列表所需的时间小于工作线程选择并执行任务所需的时间,则循环将领先于执行器服务,它会提交比您预期更多的任务。


查看完整回答
反对 回复 2023-09-06
  • 3 回答
  • 0 关注
  • 153 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号