【问题标题】:Have two different Implementations for an interface execute on different thread有两个不同的接口实现在不同的线程上执行
【发布时间】:2017-02-27 20:07:52
【问题描述】:

我有一个接口说VegetableCreation 有一个方法:

public void writeVeggieDataIntoFile();

还有两个不同的类AppleMango 实现VegetableCreation

还有一个工厂类 VegetableFactorycreate() 方法:

public class VegetableFactory {
    public VegetableCreation create(String arg0) {

        if (arg0.equals("Apple"))
           return new Apple();
        else if (arg0.equals("Mango")
           return new Mango();
        else {
           // create and return both apple and mango by spawning two different threads
           // so that the writeVeggieDataIntoFile();  gets invoked concurrently
           // for both apple and mango and two different file is created
        }
    }
}

我在这里基本上想要实现的是,当我从客户端类的main() 方法调用VegetableFactory 类的create() 方法并传递除"Apple""Mango" 以外的任何字符串值作为运行时参数。我希望两个不同的线程在每个 AppleMango 对象上工作,并在每个 writeVeggieDataIntoFile() 方法上同时工作。

任何关于设计策略/或使用哪些并发 API 等的建议都将受到高度赞赏。

P.S.:我应该叫它水果**而不是蔬菜*

【问题讨论】:

  • 这很简单。你有什么策略
  • 练习的目标是什么?学习低级线程处理?学习如何使用执行器?学习如何使用并行流?这看起来不像是使用多线程的典型用例,所以选择你想学的东西(或者你的老师想让你学的东西)。
  • @JBNizet 我需要这样做来编写两个不同的相当大的文件。苹果和芒果只是一个例子。如果我按顺序执行此过程太慢了。我在现实生活中几乎没有做过很多线程处理,所以我想在设计它时要非常小心。
  • 如果您在方法中所做的只是写入文件,并且两个文件都在同一个磁盘上,那么使其成为多线程可能会使其更慢,而不是更快。但是您可以通过简单地使用并行流或具有两个线程的执行器来测试它。
  • @shashwatZing 如果您需要创建 2 个或更多实例并且它们必须同时运行,则需要使用线程。

标签: java multithreading future runnable callable


【解决方案1】:

查看 Composite 模式,然后构建一个 CompositeVegetable,当被告知“做这件事”时,它会启动两个线程,一个做一件事,另一个做另一件事。

public class BothVegetable implements Vegetable {
    public void writeVeggieDataInfoFile() {
        Thread thread1 = new Thread(new AppleRunnable());
        Thread thread2 = new Thread(new MangoRunnable());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
    }
}

// and in your factory

    return new CompositeVegetable();

PS。你的蔬菜在我看来就像水果!

【讨论】:

  • 感谢@Edwin Buck。我会试一试,如果它有效,我想提前感谢你。我确实在这个问题上写了一个 P.s 附:我应该称它为水果**而不是蔬菜*。只是懒得到处改。
  • 我认为 BothVegetable 应该重命名为 CompositeVegetabledoIt() 重命名为 writeVeggieDataIntoFile()?
  • 是的,他们应该是。除了可能存在其他 CompositeVegetables 之外,因此需要想出一个不排除其他 CompositeVegetables 的更好的名称。也许是AppleMangoBlastVegetable
  • @EdwinBuck。所以我玩了很多不同的东西,包括执行器和并行流,但你的解决方案以最简单的方式完成了我的工作。为此,我要感谢您的支持并接受您的回答。
  • @shashwatZing 很高兴能帮上忙。祝你有美好的一天!
【解决方案2】:

我希望从名为VegetableFactory/FruitFactory 的工厂获得Vegetable/Fruit,而不是VegetableCreation/FruitCreation

我会避免线程创建和文件写入作为工厂方法中的副作用。

我还将writeFruitDataIntoFile() 重命名/更改为write(Writer out),因为您所写的内容由封闭的接口或类告知,而您写入的位置由其方法参数告知。

如果你真的需要并发处理,在write(...)中创建一个线程,让工厂方法简单地返回一个Fruit

优点是:

  • 在创建对象时没有必须记录的副作用。
  • 线程仅按需创建(以防write() 被调用),而不是在每次Fruit 对象创建时创建。
  • 您不需要额外的课程。
  • 了解工厂设计模式的每个人都一眼就能理解它的简洁实现。

见:

为了良好的 OO 实践,我会使用接口:

interface Fruit {

  void write(Writer out);

  ...
}  // Fruit

它的抽象实现:

public abstract class AbstractFruit implements Fruit {

  Data data;

  public void write(Writer out) {
    ...
  }

  ...
}  // AbstractFruit

 

public classe Apple extends AbstractFruit implements Fruit {
  ...
}

 

public classe Mango extends AbstractFruit implements Fruit {
  ...
}

为了type safety,我会使用特定的get...() 方法(通常是done in the Java API):

public class FruitFactory {

  public static Fruit getApple() {
     Fruit a = new Apple()
     ...
     return a;
  }

  public static Fruit getMango() {
     Fruit m = new Mango()
     ...
     return m;
  }
}  // FruitFactory

enum

interface Fruit {

  enum Type {
    APPLE,
    MANGO 
  }

  void write(Writer out);

  ...
}  // Fruit

 

public class FruitFactory {

  public static Fruit get(Fruit.Type fruitType) {

     switch (fruitType) {
        case Fruit.Type.APPLE:
          Fruit a = new Apple()
          ...
          return a;
          break;
        case Fruit.Type.MANGO:
          Fruit m = new Mango()
          ...
          return m;
          break;
        default:
          throw new FruitTypeNotSupported/* Runtime, i.e. unchecked */Exception();
          break; 
     }
  }  // get(...)
}  // FruitFactory

请参阅RuntimeException 的 API 文档:

未经检查的异常不需要在方法中声明 [...] throws 子句

【讨论】:

    【解决方案3】:

    首先我会让你的工厂有静态创建。然后在create do item instanceof Fruit中再创建fruit线程。 else if item instanceof Vegetable 然后做蔬菜线程。

    【讨论】:

    • 虽然静态方法在工厂中很常见,但请记住,如果您不使用静态方法,则可以拥有多个工厂实例,这在尝试换出工厂时很有用。没有static的代码基本一样,只需要复用同一个实例即可。
    • 不,我不是,但我看到我的回答也遭到了反对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多