【问题标题】:Java Threads: Specifying what should be executed in the run functionJava 线程:指定应该在 run 函数中执行的内容
【发布时间】:2009-01-21 06:07:44
【问题描述】:

我有一个连接到数据库的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
}

附: DBAdmin 是一个单例类,getInstance 方法返回自调用的实例。

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

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

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

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

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

【问题讨论】:

    标签: java multithreading singleton


    【解决方案1】:

    听起来你想要的是一个单一的线程来完成整个程序的所有数据库访问,在这种情况下你不应该将东西传递给 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
        }
    }
    

    附:多线程很难适应,但 Java 是一种很好的语言(我认为)。

    【讨论】:

      【解决方案2】:

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

      Action.java:

      enum Action {ADD, EDIT, DELETE}
      

      在 DbAdmin 中:

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

      Category.run:

      switch (_action) {
      case ADD: addCategory(this);  // or make addCategory instance method
      .....
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-15
        • 2018-11-01
        • 1970-01-01
        • 2015-03-12
        相关资源
        最近更新 更多