Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 组合两个可运行对象_Java_Multithreading_Runnable_Green Threads - Fatal编程技术网

Java 组合两个可运行对象

Java 组合两个可运行对象,java,multithreading,runnable,green-threads,Java,Multithreading,Runnable,Green Threads,比如说,我有一个名为RunnableA的Runnable,它做了一些事情。我还有一个名为RunnableB的Runnable,它执行其他操作。是否有一种方法可以将这两个Runnable以某种方式组合起来,以便它们在同一线程中运行 问题的第二部分是,如果这是可能的,那么我可以指定它们运行的顺序吗 编辑!:我之所以想这样做,是因为我需要在EDT上运行代码,但其他一些代码需要在另一个线程上运行。请看下面的代码 像这样的 public final class CompoundRunnable impl

比如说,我有一个名为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();
        }
    }
}
抱歉,如果没有很好地解释,如果您需要澄清,请发表评论


谢谢

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

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

   return retVal;
}

也许让您困惑的是Runnable与线程的关联。Runnable接口不与线程绑定,并且本身没有任何线程语义,因此您可以像上面那样轻松组合它,而不会在线程状态方面遇到麻烦。

当然,您可以创建一个
Runnable
,它只运行一个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();
        }
    }
}
public final类CompoundRunnable实现Runnable
{
私人最终可授权运行;
公共复合可运行(Iterable可运行)
{
//来自番石榴。如果需要的话,很容易用手做
this.runnables=Lists.newArrayList(runnables);
}
公共复合可运行(可运行…可运行)
{
这个(Arrays.asList(runnables));
}
@凌驾
公开募捐
{
for(Runnable-Runnable:runnables)
{
runnable.run();
}
}
}

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

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

如果您真的想运行多个Runnable,那么您可以这样做(第一个RuntimeException将退出)

注意静态便利方法,这样您就可以说“新线程(CompositeRunnable.combine(a,b,c,d…)”

另一种变体

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

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

只需创建一个新类
RunList
,该类对具体的
List
实现(例如
ArrayList
)之一进行子类化,然后声明它实现了
Runnable

公共类RunList扩展ArrayList实现Runnable{
@凌驾
公开募捐{
for(可运行的跑步者:此){
runner.run();
}
}
}
定义了该类之后,您就可以开始定义:

RunList runList = new RunList() 
然后用所有要运行的
可运行项填充
runList
。现在,您可以在这里使用完整的Java语言和标准库对列表进行重新排序或常规操作

下面包括一些示例(未测试)用法

public void testRunList(){
运行列表=新的运行列表();
//古老的、直截了当的技术
对于(int i=0;i<10;++i){
列表。添加(()->{
/*我是runnable*/
});
}
//简单地向列表中添加任意数量的Runnable的一点类型转换
list.addAll(Arrays.asList(
()->{/*可运行1*/},
()->{/*可运行2*/}
));
//或者,如果你只是觉得很兴奋,这些方法也可以由你来决定!
集合。洗牌(列表);
list.run();
}

如果您需要在同一个线程上以指定的顺序运行这些线程,这并不完全是多线程问题。你能从runnables中提取你的代码吗?非常感谢。我对您的代码进行了一些修改,并在上面的示例中使用了它。你能告诉我你的想法吗?@user489041:好吧,你已经删除了泛型,开始。。。为什么?@Jon Skeet我不能使用函数列表。newArrayList(runnables)。这是com.google.common.collect.list的一部分吗?@user489041:是的。但是,即使您想自己创建一个新的
ArrayList
并手动创建,也值得使用泛型。@user489041:泛型基本上是关于类型安全的-例如,确保您不要尝试将字符串放入整数列表中。我强烈建议你仔细阅读。是的,我想这就是我感到困惑的原因。我觉得我想得太多了。我在寻找一种通用方法,可以在EDT上启动和关闭一些代码,然后在它自己的线程中运行一些工作者代码。这就是为什么我想知道是否可以用这种方式将它们结合起来。我基于响应的尝试已在上面发布。可能应该捕获第一个异常并将其传递给未捕获的异常处理程序。不幸的是,
Runnable
没有什么意义。
public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}
RunList runList = new RunList()