【问题标题】:how can i structure a multi-threaded code for better code reuse in java?我如何构建多线程代码以更好地在 java 中重用代码?
【发布时间】:2012-07-02 22:11:31
【问题描述】:

我正在用 Java 构建一个多线程项目,我有实体和 DAO 包来包装数据库表并对其进行操作。我有包含 Runnables 的处理包。到目前为止,我实现 Runnables 的方式是这样的:

Class Thread1 implements Runnable{
  Thread t;
   parameters
  ...

  public Thread1(){
    t = new Thread(this,"Thread1");
    ....
    t.start();
  }

  public int method1(){
  ...
  return x;
  }

  public double method2(){
  ...
  return y;
  }

  public void run(){
    // some processing using DAO methods
    ....
    method1();
    ... 
    method2();
    ...
  }

}

代码以这种方式工作,但我需要在run() 方法中使用相同的处理作为Thread2 类中处理的一部分。我构建代码的方式不允许重用代码。解决这个问题的更好结构是什么?

【问题讨论】:

  • 旁注:你为什么叫 Runnable Thread1?为什么不Runnable1
  • @assylias 我正在里面创建一个线程,这就是为什么

标签: java multithreading code-reuse code-structure


【解决方案1】:

你可以:

  1. 使Thread1Thread2 扩展同一个抽象基类,并将共享逻辑移至父级(继承)。
  2. 创建一个公共接口,两个类都实现并包含公共方法,然后创建一个单独的类来实现Runnable,并在那里实现run()(组合)。

您应该始终支持组合而不是继承,因此第二个选项通常更好,因为它还为您提供了在运行时更改行为的灵活性。

例如: 先创建一个共享接口

public interface SharedTask {
    public void method1();
    public void method2();
}

让两个类都实现它: public class Thread1 implements SharedTaskpublic class Thread2 implements SharedTask

public class Worker implements Runnable {

    public Worker (SharedTask task) {
        this.task = task;
        ...
    }

    public void run() {
        task.method1();
        task.method2();
    }
}

代码中的其他地方: new Worker().start();

【讨论】:

  • 我没有得到第二个选项.. 所以这两个类都不是 Runnables?他们会创建一个单独的 Runnable 类的实例吗?如果是这种情况,run 方法会包含什么内容?
  • 得到了它,但是这样公共方法将在两个类中实现两次(这些公共方法的实现是相同的)。有没有像您建议的那样避免在超类中实现它们以避免继承。
  • 对于共享功能,最好将SharedTask 作为一个抽象类并在那里实现它们并使用两种方法的混合解决方案。没有一般的经验法则说扩展是不好的,你只需要小心不要过度使用它,因为它会降低你的代码的可重用性。
【解决方案2】:

您几乎从不想自己创建和启动线程。只需实现 Runnable(或者,如果您愿意,也可以实现 Callable)。然后将它们提交给ExecutorService,它提供了各种很酷的选项来确定它正在运行的线程数(以及一个很好的中心位置,可以在您的需求发生变化时在未来进行更改)、与 CompletionService 的关联等。 ..

【讨论】:

    【解决方案3】:

    创建一个抽象类,在其 run 方法中使用您想要的代码实现 Runnable - 然后根据您的 run 方法中的相同功能多次扩展该类。

    【讨论】:

      【解决方案4】:

      在深入了解多线程的精妙细节之前:您的所有 DAO 调用可能都将在一个数据库连接上运行,因此(几乎)在一个数据库线程上运行。 (特别是如果使用一些 ORM 框架,但是一个简单的数据源池会给你同样的效果)你绝对可以摆脱这个问题,但这意味着你必须使用具有两阶段提交的 XA 资源来保持 ACID 兼容。这一大块工作,所以除非你准备好这样做,否则考虑应用服务器端多线程的细微差别是没有意义的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-30
        • 1970-01-01
        • 1970-01-01
        • 2021-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-19
        相关资源
        最近更新 更多