猿问

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

我有一个列表说有登录名,基于列表内容,我正在处理其他方法,例如:


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。我哪里做错了?


爱!!


交互式爱情
浏览 154回答 3
3回答

阿晨1998

您的方法不是线程安全的。it.hasNext()在每次迭代时调用,因此您可以相信获得了预期结果,但Iterator不是线程安全的。因此,如果同时执行多个Callables,则使用迭代器会产生不可预测的结果。使用 Thread 或 Callable 当然可以利用并行性,但在使用迭代器时需要添加显式同步。虽然使用Callable显式同步在某种程度上很烦人。作为替代方案,您可以使用确保线程安全的集合,例如CopyOnWriteArrayList.&nbsp;例如,将原始列表包装在CopyOnWriteArrayList复制构造函数中,例如:List<Foo>&nbsp;copyList&nbsp;=&nbsp;new&nbsp;CopyOnWriteArrayList<>(list);或者,您也可以更简单地使用并行流,这将使您的代码变得不那么冗长,但它在幕后的线程池的可配置性较低(在某些情况下,这很重要):list.parallelStream().forEachOrdered(this::method1);

杨__羊羊

首先尝试获取迭代值。final <class> nextItem = it.next();Future<?> future = service.submit(() -> { method1(nextItem); });futures.add(future);

LEATH

我哪里做错了?你有一个线程正在执行此操作:while&nbsp;(&nbsp;it.hasNext()&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Future<?>&nbsp;future&nbsp;=&nbsp;service.submit(...task...); &nbsp;&nbsp;&nbsp;&nbsp;futures.add(future); }该线程不断调用it.hasNext(),但它从不调用it.next()。您还有其他线程(线程池的工作线程)在调用,it.next()但这些线程独立于循环运行。如果循环向执行器服务提交任务并将 future 添加到列表所需的时间小于工作线程选择并执行任务所需的时间,则循环将领先于执行器服务,它会提交比您预期更多的任务。
随时随地看视频慕课网APP

相关分类

Java
我要回答