组合两个 Runnable 对象

发布于 2024-10-11 23:14:03 字数 1928 浏览 9 评论 0原文

举例来说,我有一个名为 RunnableA 的 Runnable,它可以执行某些操作。我还有一个名为 RunnableB 的 Runnable,它可以执行其他操作。有没有办法可以将这两个 Runnable 组合起来,以便它们在同一个线程中运行?

问题的第二部分是如果这可能的话,我可以指定它们运行的​​顺序吗?

编辑!:我想这样做的原因是因为我需要在 EDT 上运行代码,但其他一些代码需要在另一个线程上运行。请看下面的代码。

像这样的事情


public final class CompoundRunnable implements Runnable
{
    private final Iterable runnables;

    public CompoundRunnable(Iterable runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);

    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}


public void setStatusAndProgress(final String status,Runnable runnable)
    {
        Runnable startUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus(status);
                        selfReference.getProgressBar().setIndeterminate(true);
                    }

                });
            }
        };
        Runnable cleanUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus("");
                        getProgressBar().setIndeterminate(false);
                    }
                });
            }
        };

        Runnable theRunner = new CompoundRunnable(startUpRunner,runnable,cleanUpRunner);
        new Thread(theRunner).start();
    }

抱歉,如果解释得不好,如果您需要澄清,请发表评论。

谢谢!

Say for example that I have a Runnable called RunnableA that does something. I also have a Runnable called RunnableB that does something else. Is there a way that I can combine these two Runnables someway so that they will run in the same thread?

The second part of the question is if this is possible, can I then specify the order that they will run in?

EDIT!: The reason why I wanted to do this was because I need to run code on the EDT but some of the other code needs to be run on another thread. Please take a look at the code below.

Something like this


public final class CompoundRunnable implements Runnable
{
    private final Iterable runnables;

    public CompoundRunnable(Iterable runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);

    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}


public void setStatusAndProgress(final String status,Runnable runnable)
    {
        Runnable startUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus(status);
                        selfReference.getProgressBar().setIndeterminate(true);
                    }

                });
            }
        };
        Runnable cleanUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus("");
                        getProgressBar().setIndeterminate(false);
                    }
                });
            }
        };

        Runnable theRunner = new CompoundRunnable(startUpRunner,runnable,cleanUpRunner);
        new Thread(theRunner).start();
    }

Sorry if this isnt explained well, post comments if you need clarification.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

↙厌世 2024-10-18 23:14:03

好吧,你当然可以创建一个 Runnable ,它只运行一个可运行的,然后运行另一个:

public final class CompoundRunnable implements Runnable
{
    private final Runnable first;
    private final Runnable second;

    public CompoundRunnable(Runnable first, Runnable second)
    {
        this.first = first;
        this.second = second;
    }

    @Override
    public void run()
    {
        first.run();
        second.run();
    }
}

更一般地,你可以让它采用一个 Iterable,复制所有 Runnable 引用,然后按顺序运行它们。例如:

public final class CompoundRunnable implements Runnable
{
    private final Iterable<Runnable> runnables;

    public CompoundRunnable(Iterable<Runnable> runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);
    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}

Well you can certainly create a Runnable which just runs one runnable then the other:

public final class CompoundRunnable implements Runnable
{
    private final Runnable first;
    private final Runnable second;

    public CompoundRunnable(Runnable first, Runnable second)
    {
        this.first = first;
        this.second = second;
    }

    @Override
    public void run()
    {
        first.run();
        second.run();
    }
}

More generally, you could make it take an Iterable<Runnable>, copy all the Runnable references, and then run them in order. For example:

public final class CompoundRunnable implements Runnable
{
    private final Iterable<Runnable> runnables;

    public CompoundRunnable(Iterable<Runnable> runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);
    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}
夏尔 2024-10-18 23:14:03

当然。只需创建另一个可运行对象,该可运行对象调用两个现有可运行对象的运行方法作为其实现的一部分。您可以使用 Runnable 列表等来专门构建或通用包装 Runnable。

public Runnable combineRunnables(Runnable a, Runnable b)
{
   Runnable retVal = new Runnable()
   {
        public void run()
        {
            a.run();
            b.run();
        } 
   };

   return retVal;
}

也许让您感到困惑的是 Runnable 与线程的关联。 Runnable 接口不与线程绑定,并且本身不具有任何线程语义,因此您可以像上面一样轻松地组合它,而不会以某种方式陷入线程状态的麻烦。

Sure. Just create another runnable that calls the run methods of your two existing Runnable's as part of its implementation. You can make the wrapping Runnable purpose-built or generic with a list of Runnables, etc.

public Runnable combineRunnables(Runnable a, Runnable b)
{
   Runnable retVal = new Runnable()
   {
        public void run()
        {
            a.run();
            b.run();
        } 
   };

   return retVal;
}

Perhaps what's confusing you is association of Runnable with threads. The Runnable interface isn't tied to threads and doesn't by itself have any threading semantics, so you can easily combine it like above without somehow getting into trouble with thread states.

沫雨熙 2024-10-18 23:14:03

是的,您当然可以将它们结合起来。但一般来说,除了调用其他对象以实际完成工作之外,可运行对象内部不应该有太多内容。您能不能只获取您需要的可运行对象的“内部”并在您想要的上下文中执行它们。

如果您想确保事情只是一个接一个地执行,而不是同时执行,您可以使用 SingleThreadExecutorService 并为它们提供 Runnables。它将一次执行一个。

如果您确实想运行多个可运行对象,那么您可以这样做(第一个 RuntimeException 将退出)。

请注意静态便捷方法,因此您可以说“new Thread(CompositeRunnable.combine(a,b,c,d...))”

public class CompositeRunnable implements Runnable {

    private final Runnable[] runnables;

    public CompositeRunnable(Runnable... runnables) {
        this.runnables = runnables;
    }

    public void run() {
        for (Runnable runnable : runnables) {
            runnable.run();
        }
    }

    public static Runnable combine(Runnable... runnables) {
        return new CompositeRunnable(runnables);
    }
}

Yes you can of course combine them. In general though, there shouldn't be much inside a runnable except a call to some other object, to actually get the work done. Can you not just take the "insides" of the runnables you need and execute them in the context you want.

If you want to make sure things are simply executed one after the other, rather than at the same time you can use a SingleThreadExecutorService and give them the Runnables. It will execute one at a time.

If you really want to run multiple runnables then you can do it like this (the first RuntimeException will exit).

Note the static convenience method so you can say "new Thread(CompositeRunnable.combine(a,b,c,d....))"

public class CompositeRunnable implements Runnable {

    private final Runnable[] runnables;

    public CompositeRunnable(Runnable... runnables) {
        this.runnables = runnables;
    }

    public void run() {
        for (Runnable runnable : runnables) {
            runnable.run();
        }
    }

    public static Runnable combine(Runnable... runnables) {
        return new CompositeRunnable(runnables);
    }
}
骷髅 2024-10-18 23:14:03

另一种变化。

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}

Another variation.

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}
还在原地等你 2024-10-18 23:14:03

我很惊讶没有人提出更灵活的方法,与现有答案相比,这恰好也是最简单和最短的解决方案。

只需创建一个新类 RunList,该类是具体 List 实现之一(例如 ArrayList)的子类,然后声明它实现 Runnable code>

public class RunList extends ArrayList<Runnable> implements Runnable {
    @Override
    public void run() {
        for (Runnable runner : this) {
            runner.run();
        }
    }
}

定义该类后,您可以继续定义:

RunList runList = new RunList() 

然后使用您想要运行的所有 Runnables 填充 runList。现在,您可以使用完整的 Java 语言和标准库来对列表进行重新排序或常规操作。

下面包含一些示例(未经测试)用法。

public void testRunList() {

    RunList list = new RunList();

    // the venerable, straight-forward technique
    for (int i = 0; i < 10; ++i) {
        list.add(() -> {
            /* i'th runnable */
        });
    }

    // a bit of type juggling to concisely add an arbitrary number of Runnables to the list
    list.addAll(Arrays.asList(
        () -> { /* runnable 1 */ },
        () -> { /* runnable 2 */ }
    ));

    // or if you're just feeling frisky, these methods too are at your disposal!
    Collections.shuffle(list);

    list.run();
}

I'm surprised nobody suggested the more flexible approach, which just so happens to be also the simplest and and shortest solution compared to the existing answers.

Just create a new class RunList that subclasses one of the concrete List implementations (e.g. ArrayList) and then declare it implements Runnable

public class RunList extends ArrayList<Runnable> implements Runnable {
    @Override
    public void run() {
        for (Runnable runner : this) {
            runner.run();
        }
    }
}

With that class defined, you can then go about defining:

RunList runList = new RunList() 

And then populate runList with all of the Runnables you want to run. You now have the full Java language and standard library at your disposal here for reordering or general manipulation of the list.

Some example (untested) usage is included below.

public void testRunList() {

    RunList list = new RunList();

    // the venerable, straight-forward technique
    for (int i = 0; i < 10; ++i) {
        list.add(() -> {
            /* i'th runnable */
        });
    }

    // a bit of type juggling to concisely add an arbitrary number of Runnables to the list
    list.addAll(Arrays.asList(
        () -> { /* runnable 1 */ },
        () -> { /* runnable 2 */ }
    ));

    // or if you're just feeling frisky, these methods too are at your disposal!
    Collections.shuffle(list);

    list.run();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文