1

我正在和我的团队一起做一个 java 项目。总而言之,我们有一个主类,它有一个实例化和调用“保存”类的方法。这个“保存”类使用几个构造函数和一些可见和不可见的方法将文件保存回服务器。该类是 CPU 密集型和耗时的,这会阻止主应用程序显示进度条对话框窗口,让用户知道保存的状态。他们要求我修改“保存”类,使其产生自己的线程,以便主应用程序的其余部分可以完成向用户显示信息的较小任务。

这是它的一般概念:

class MainApp{  
    ...

    private void doSave()
    {
        Save s = new Save();
        StatusWindow sw = new StatusWindow();

        if save_this
          s.saveThis(sw);
        if save_that
          s.saveThat(sw);

        ...
    }
    ...
}

class Save{
   ...

   public void saveThis(StatusWindow s)
   {
       //alot of code
       s.update;

   }
   public void saveThat(StatusWindow s)
   {
       //alot of code
       s.update;
   }
   ... // some non-visible methods, even more code
 }

我目前是 Java 线程的新手,但我对它们的工作原理有基本的了解。据我了解,一个实现 Runnable 的类,当它被实例化为一个新线程时,就会执行 run() 方法。问题是,由于不同类型的文件有不同类型的保存方法,我如何将这些方法实现到 run() 方法中?run() 方法是在新线程中实例化类并在其上调用 .start() 时执行的唯一方法吗?

什么是解决这个问题的好方法?是否需要重新设计“Sa​​ve”类以使其实现 Runnable?

如果需要更多详细信息,请告诉我。感谢您的任何见解!

更新:感谢大家的帮助!这些解决方案将在未来派上用场。

4

4 回答 4

7

最简单的方法是为每个创建一个可运行的。不要将参数传递给运行,而是将它们设为实例字段。

class SaveThatCommand implements Runnable {
     private final StatusWindow s;
     //constructor that initializes s
     public void run() {
        //save that code
        s.update();
     }
}

根据您的要求,一种更简单的方法是创建一个匿名内部类

public void doSave(final StatusWindow s) {
    if (saveThis) {
        Thread t = new Thread( new Runnable() {
            public void run() {
               saveThis(s);
            }
        });
        t.start();
    }
    //...
}

而且您有点不正确: run 方法在传递给 Thread 的构造函数时执行,然后在该 thread 上调用 start()

于 2010-09-22T19:36:56.700 回答
3

您的同事可能从主应用程序中的多个位置调用 Save,并且希望避免更改所有其他代码以支持将保存为并行操作。此外,一般来说,大多数人不喜欢创建自己的线程,而是更喜欢使用 ExecutorService。所以这里是如何只修改 Save 类并使用执行器来做到这一点:

class Save{
   private static final ExecutorService executor = Executors.newCachedThreadPoolExecutor();
   //or fixed, or whatever you want. Maybe single thread executor is best if the Save code is not well suited to concurrency.

   static {
       Runtime.getRuntime().addShutdownHook(
           new Thread() {
               public void run() {
                   executor.shutdown();
               }
           }
       );
   }

   public void saveThis(StatusWindow s)
   {
      executor.execute(new SaveThis(s));
   }
   public void saveThat(StatusWindow s)
   {
      executor.execute(new SaveThat(s));
   }
   ... // some non-visible methods, even more code

   private class SaveThis implements Runnable {
       //StatusWindow member variable and constructor
       public void run() {
           //alot of code
           s.update;
       }
   }

   private class SaveThat implements Runnable {
       //StatusWindow member variable and constructor
       public void run() {
           //alot of code
           s.update;
       }
   }
 }
于 2010-09-23T02:17:05.820 回答
2

一个完整的解决方案是扩展Runnable类并传入所需的参数以及构造函数所需的保存类型。然后你可以运行它们:

新线程(saveRunnable).start();

一个更简单的解决方案是在保存类中实现这样的模式:

公共无效 saveThis(StatusWindow s) {
  可运行 r = new Runnable() {
     私有状态窗口;
     公共可运行 setStatusWindow(StatusWindow s) {
       这.s = s;
       返回这个;
     }

     @覆盖
     公共无效运行(){
       this.Save.saveThisInternal(this.s);
     }
  }.setStatusWindow(s);
  新线程(r).start();
}

公共无效 saveThisInternal(StatusWindow s) {
  //很多代码
  s.update();
}
于 2010-09-22T19:44:49.777 回答
0

有两种方法可以做到这一点:

a) 您可以将带有 if 块的代码移动到 run() 方法中。

b)您可以为每个文档类型设置一个实现可运行的类。

方法 a) 更简单,因为它需要对现有代码的更改更少。但是方法 b) 是面向对象的方法:“每个任务一个类”。

于 2010-09-22T19:41:52.157 回答