我正在与我的团队一起开展一个Java项目。总而言之,我们有一个主类,它有一个实例化并调用“Save”类的方法。这个“保存”类将文件保存回服务器,其中包含几个构造函数和一些可见和不可见的方法。该类占用大量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()时执行的唯一方法吗?
这个问题的解决方案是什么?是否需要重新设计“Save”类以使其实现Runnable?
如果需要更多详细信息,请告知我们。感谢您的任何见解!
更新:感谢大家的帮助!这些解决方案将为未来派上用场。
答案 0 :(得分:7)
最简单的方法是为每个人制作一个可运行的。不是将参数传递给run,而是将它们作为实例字段。
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 的构造函数时执行,然后在该线程上调用start()。
答案 1 :(得分: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;
}
}
}
答案 2 :(得分: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 :(得分:0)
有两种方法可以做到:
a)您可以使用if-block将代码移动到run()方法中。
b)每个文档类型可以有一个实现runnable的类。
方法a)更简单,因为它需要对现有代码进行较少的更改。但方法b)是面向对象的方式:“每个任务一个类”。