我有一种奇怪的行为我无法解释。
请看一下这个最小的例子:
public class ParallelStreamProgressMonitor
{
public static void main(String[] args)
{
List<Integer> belege = IntStream.range(1, 100).boxed().collect(Collectors.toList());
final ProgressMonitor pm = new ProgressMonitor(null, "Initialmessage", "Initial Note", 0, belege.size());
pm.setMillisToDecideToPopup(0);
pm.setMillisToPopup(0);
pm.setMaximum(belege.size());
pm.setNote("Now I am working");
AtomicInteger counter = new AtomicInteger();
belege.stream().parallel().forEach(b ->
{
System.out.println(b);
pm.setProgress(counter.getAndIncrement());
try
{
//something time consuming ...
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// ignore
}
});
}
}
在执行此操作时,通常会出现progressmonitor并显示执行的进度。
但事实是这样的:
似乎对于每个并行流执行,都有一个额外的progressmonitor示例出现。
有什么原因吗?我怎样才能做到只有一个对话框出现并显示进度?
2条答案
按热度按时间qvtsj1bj1#
考虑swing的线程策略:
一般来说,swing不是线程安全的。除非另有说明,否则必须在事件调度线程上访问所有swing组件和相关类。
这意味着你必须学习
ProgressMonitor
的文档来确定“除非另有说明”是否适用,但是由于没有其他线程策略,这里没有什么可引用的。在事件调度线程中执行操作的一种方法是将其封装在
Runnable
使用invokeLater(Runnable)
,但是当这样做是为了从未知数量的工作线程发送不同的进度状态时,它们可能会以错误的顺序到达,而且效率也会非常低。既然你已经有了AtomicInteger
,更好的选择是使用秋千Timer
:3qpi33ja2#
是否真的需要使用并行处理?如果不更换
belege.stream().parallel().forEach(b ->
与belege.stream().forEach(b ->
,它应该能解决你的问题。并行执行将涉及更多线程,因此将从不同上下文对进度监视器进行多个调用。每个线程将显示一个进度ui,最终您将拥有多个进度ui。因此,如果您没有真正的理由使用并行执行,请使用顺序执行。