1

我有一个DBAdmin连接到数据库的类,然后还有一些其他类,例如等ArticleCategory它们对数据库执行某些查询。

我在 Swing 应用程序中使用这些类来构建一种小型 Intranet CMS 应用程序。

现在,Category该类有一堆static方法,例如addCategoryeditCategory等等,例如:

public class Category implements Runnable {

    public void run () {
        //Code that will be executed in a separate thread, from the Runnable Interface
    }

    public static int addCategory(Category cat) {
        DBAdmin db = DBAdmin.getInstance();
        db.connectDB();
        //rest of the code that creates sql statement and so on...
    }

    //Other static edit and delete methods that will be called from outside
}

PSDBAdmin是一个Singleton Class,getInstance方法返回自调用的实例。

现在,我想要做的是数据库操作应该在与应用程序不同的线程中运行,并且我设法做了一些示例测试,这些测试在 a isrun时在方法中运行。Threadstarted

但问题是我无法指定在run启动线程时应该在方法中运行哪个方法。

从某种意义上说,例如当addCategory从外部调用时,该run方法应该调用addCategory它内部的方法。

有没有办法将函数作为回调参数从方法传递给 run 方法,addCategory以便它知道在启动新线程时应该在其中调用哪个函数?还是有一种完全不同的方式来实现我想要做的事情?

PS我在这一点上对Java“相当”陌生,尤其是多线程,所以我可能在这里遗漏了一些东西。

4

2 回答 2

7

听起来您想要的是一个线程,它为整个程序执行所有数据库访问,在这种情况下,您不应该将东西传递给 run 方法。因为当你有一个线程时,它所做的只是调用一个 run 方法,当它启动时,那个 run 方法会一直执行,直到它返回或线程被强制终止。做这种事情的方法是有一个同步队列,比如说,在你的 DBAdmin 类中。然后像 addCategory 这样的方法将准备它们的语句并将它们添加到这个共享队列中。单个数据库线程一次处理队列中的语句,当语句完成时,它通知将其添加到队列中的线程。事实上,Java(至少是最近的版本)包括一组可以为您做这些的类;他们' 重新称为 Executors,它们可以在 java.util.concurrent 包中找到。具体来说,查看 java.util.concurrent.Executors.newSingleThreadExecutor() 方法,这是我在这种情况下使用的方法。

class SQLQueryCallable implements Callable<SQLResultSet> {
    private String query;
    public SQLQueryCallable(String query) {
        this.query = query;
    }
    public SQLResultSet Call() throws Exception {
        // execute query
        return results;
    }
}
ExecutorService ex = Executors.newSingleThreadExecutor();

// in DBAdmin somewhere:
    public SQLResultSet runQuery(String query) {
        Future<SQLResultSet> f = ex.submit(new SQLQueryCallable(query));
        return f.get(); // this waits for the query to complete
    }

如果我一直误读您的问题,并且您实际上希望每个数据库查询在其自己的线程中执行,那么我建议创建一个名为 SQLQuery 之类的类,它实现 Runnable(或扩展 Thread)-实际上,您甚至可以考虑使用 java.util.concurrent.Callable,它允许您从其 call() 方法(类似于 run())返回一个值。类构造函数应该将 SQL 语句作为参数,并且它的 run 方法应该完成执行该语句的工作。然后,如果您使用过 Callable,则可以返回语句的结果,或者如果您使用过 Runnable,则可以将其存储在某个通常可访问的位置。这就是您所问问题的简单答案,即如何将数据传递给 run() 方法:使用类构造函数。

class SQLQueryRunnable implements Runnable {
    private String query;
    public SQLQueryRunnable(String query) {
        this.query = query;
    }
    public void run() {
        // execute query
    }
}

PS 多线程是一件很难习惯的事情,但 Java 是一种很好的语言(我认为)。

于 2009-01-21T06:41:43.053 回答
0

正如 Adeel 指出的那样,您似乎将数据和操作混合在一个类中。但是,如果您想坚持这一点,您可以在 Category 中添加一个命令字段,该字段可以在 run 方法中的开关(或某些此类)中使用。

动作.java:

enum Action {ADD, EDIT, DELETE}

在 DbAdmin 中:

Category c = new Category(Action.ADD, /* other category parameter */);
c.start();

类别运行:

switch (_action) {
case ADD: addCategory(this);  // or make addCategory instance method
.....
}
于 2009-01-21T06:26:56.437 回答