首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有Progressmonitor的并行流打开多个对话框

带有Progressmonitor的并行流打开多个对话框
EN

Stack Overflow用户
提问于 2020-12-18 10:13:48
回答 2查看 69关注 0票数 1

我有一种我无法解释的奇怪行为。

请看一下这个最小的例子:

代码语言:javascript
复制
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实例出现。

这有什么原因吗?如何才能实现只有一个对话框显示并显示进度?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-18 10:49:23

考虑一下Swing的线程策略

一般来说,Swing并不是线程安全的。除非另有文档说明,否则所有Swing组件和相关类都必须在事件调度线程上访问。

这意味着您必须研究[经]文件,以确定“除非另有文档”是否适用,但是由于没有其他线程策略,这里没有什么可引用的。

在事件调度线程中执行操作的一种方法是将其封装到Runnable中并使用invokeLater(Runnable),但是当使用它从数量未知的工作线程发送不同的进度状态时,它们可能到达错误的顺序,而且效率也很低。因为您已经有了一个AtomicInteger,所以更好的选择是使用Timer

代码语言:javascript
复制
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();
        Timer timer = new Timer(250, ev -> pm.setProgress(counter.get()));
        timer.start();
        belege.stream().parallel().forEach(b ->
        {
            System.out.println(b);
            counter.getAndIncrement();
            //simulate something time consuming ...
            LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000));
        });
        timer.stop();
    }
}
票数 2
EN

Stack Overflow用户

发布于 2020-12-18 10:46:29

是否真的需要使用并行处理?如果不将belege.stream().parallel().forEach(b ->替换为belege.stream().forEach(b ->,它将解决您的问题。

并行执行将涉及更多的线程,因此将从不同的上下文中多次调用进度监视器。每个线程都将显示一个进度UI,最终您将拥有多个进度UI。因此,如果您没有真正的理由使用并行执行,那么就进行顺序执行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65355156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档