2010-09-22 39 views
1

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

这里是它的一个笼统的概念:

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()时被执行的唯一方法吗?

这将是一个很好的解决方案这个问题? “Save”类是否需要重新设计才能实现Runnable?

如果需要更多的细节,请让我知道。感谢您的任何见解!

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

回答

7

最简单的方法是为每个运行一个runnable。而不是参数传递到运行,使他们实例字段。

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方法线程的构造函数,然后在该线程上调用start()。

+0

是的我完全忘了在那里添加.start(),我会编辑我的问题。 Thanx :) – 2010-09-22 19:43:25

+0

我喜欢第二个建议,现在看起来很快且容易实现 – 2010-09-23 13:47:14

0

有这样做的方法有两种:

a)您可以与如果块到run()方法移动代码。

b)每个文档类型可以有一个实现可运行的类。

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

2

完整的解决方案是扩展Runnable类,并将所需参数和保存类型传递给构造函数。然后,你可以运行它们:

new Thread(saveRunnable).start();

一个简单的解决办法是实施保存类中像这样的模式:

 
public void saveThis(StatusWindow s) { 
    Runnable r = new Runnable() { 
    private StatusWindow s; 
    public Runnable setStatusWindow(StatusWindow s) { 
     this.s = s; 
     return this; 
    } 

    @Override 
    public void run() { 
     this.Save.saveThisInternal(this.s); 
    } 
    }.setStatusWindow(s); 
    new Thread(r).start(); 
} 

public void saveThisInternal(StatusWindow s) { 
    //alot of code 
    s.update(); 
} 
3

你的同事可能来自多个地方的主要调用保存应用程序,并希望避免必须更改所有其他代码以支持将其另存为并行操作。另外,一般来说,大多数人不喜欢自己创建线程,而更喜欢使用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; 
     } 
    } 
} 
+0

+1 Thanks Tim!我将继续关注未来 – 2010-09-23 13:48:28