[英]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.


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:


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();
        //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.


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


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


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?


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


2 个解决方案


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.


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).



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.


enum Action {ADD, EDIT, DELETE}

in DbAdmin:

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

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



粤ICP备14056181号  © 2014-2021