Java線程:指定應該在run函數中執行的內容

[英]Java Threads: Specifying what should be executed in the run function


I have a DBAdmin class that connects to the database, and then some other classes such as Article, Category and so on, that perform certain queries to a database.

我有一個連接到數據庫的DBAdmin類,然后是一些其他類,如Article,Category等,它們對數據庫執行某些查詢。

I am using these classes in a Swing application to build a sort of small Intranet CMS application.

我在Swing應用程序中使用這些類來構建一種小型Intranet CMS應用程序。

Now, the Category class has a bunch of static methods such as addCategory, editCategory and so on, like such:

現在,Category類有一堆靜態方法,如addCategory,editCategory等,如下所示:

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
}

P.S. The DBAdmin is a Singleton Class, and the getInstance method returns the self invoked instance.

附: DBAdmin是Singleton類,getInstance方法返回自調用的實例。

Now, what I'm trying to do is that the database actions should be run in a separate thread from the application, and I managed to do some sample tests that are run in the run method when a Thread is started.

現在,我要做的是數據庫操作應該在與應用程序不同的線程中運行,並且我設法在啟動Thread時在run方法中運行一些示例測試。

But the problem is that I cannot specify which method should be run in the run method when a thread is started.

但問題是我無法指定在啟動線程時應該在run方法中運行哪個方法。

In the sense that when for example the addCategory is called from the outside, the run method should invoke the addCategory method inside it.

從某種意義上說,當從外部調用addCategory時,run方法應該調用其中的addCategory方法。

Is there a way to maybe pass a function as a callback parameter to the run method from the addCategory method so that it will know what function should be invoked in it when a new thread is started? Or is there a completely different way to achieve what I'm trying to do?

有沒有辦法可以將一個函數作為回調參數從addCategory方法傳遞給run方法,以便在啟動新線程時知道應該在其中調用哪個函數?或者是否有一種完全不同的方式來實現我想要做的事情?

P.S. I am 'fairly' new to Java at this point, especially multi-threading, so I may be missing something here.

附:到目前為止,我“相當”不熟悉Java,特別是多線程,所以我可能會在這里遺漏一些東西。

2 个解决方案

#1


It sounds like what you want is a single thread which does all the database access for the whole program, and in that case you shouldn't be passing things to the run method. Because when you have a single thread, all it does is call a single run method once, when it starts, and that run method just keeps executing until it returns or the thread is forcibly terminated. The way to do that sort of thing is to have a synchronized queue, say, in your DBAdmin class. Then methods like addCategory would prepare their statements and add them to this shared queue. The single database thread processes the statements in the queue one at a time, and when a statement completes, it notifies the thread that added it to the queue. In fact, Java (recent versions at least) includes a set of classes that will do exactly that for you; they're called Executors and they can be found in the java.util.concurrent package. Specifically, look at the java.util.concurrent.Executors.newSingleThreadExecutor() method, which is what I'd use for a situation like this.

聽起來你想要的是一個單一的線程,它為整個程序進行所有數據庫訪問,在這種情況下,你不應該將事物傳遞給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
    }

If I've been misreading your question, and you actually want each database query to execute in its own thread, then I'd suggest making a class called something like SQLQuery, which implements Runnable (or extends Thread) - actually, you could even consider using java.util.concurrent.Callable, which allows you to return a value from its call() method (which is like run()). The class constructor should take an SQL statement as a parameter, and its run method should do the work to execute that statement. Then if you've used Callable, you can return the result of the statement, or if you've used Runnable, you can store it in some commonly accessible location. That's the simple answer to what you were asking about, how to pass data to a run() method: use the class constructor.

如果我一直在誤讀你的問題,而你實際上希望每個數據庫查詢都在自己的線程中執行,那么我建議創建一個類似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
    }
}

P.S. Multithreading is a hard thing to get used to but Java is a good language to do it in (my opinion).

附:多線程是一個很難習慣的東西,但Java是一種很好的語言(我認為)。

#2


As Adeel pointed out, you seem to be mixing the data and operation in a single class. But if you want to stick to that, you can add a command field in Category, that can be used in a switch (or some such) in the run method.

正如Adeel指出的那樣,您似乎將數據和操作混合在一個類中。但是如果你想堅持這一點,你可以在Category中添加一個命令字段,該字段可以在run方法的開關(或某些類似的)中使用。

Action.java:

enum Action {ADD, EDIT, DELETE}

in 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
.....
}

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/01/21/72502865c6290515f32e1e8e961f2853.html



函數和綁定:它們是什么?應該在什么時候使用? - std::function and std::bind: what are they & when they should be used? 我應該在Java程序中使用多少個線程? - How many threads should I use in my Java program? 我應該在rails中為postgresql函數創建遷移嗎? - Should I create a migration for a postgresql function in rails? 為什么我應該在自包含函數中引用jQuery? - Why should I reference jQuery in a self contained function? 在WPF窗口的構造函數中,應該在InitializeComponent()之前進行什么以及之后的內容? - In a constructor for a WPF Window, what should go before InitializeComponent() and what after? 什么時候應該在執行器上使用Java的線程? - When should we use Java's Thread over Executor? 什么時候應該在Array上使用isset()而不指定鍵? - When isset() should be used on Array without specifying key? 我應該在`included do ... end`塊中包含哪些內容? - What should I not include in the `included do … end` block? Java中的本機方法是什么,它們應該在哪里使用?(復制) - What are native methods in Java and where should they be used? [duplicate] 如果在線程的run函數中執行return語句,則線程在java中停止 - If return statement is executed in run function of a thread does the thread stop in java
 
粤ICP备14056181号  © 2014-2020 ITdaan.com