1

我正在编写一个使用一些线程的 Java 应用程序。主要方法如下所示:

WorkerThread[] thread = new WorkerThread();
for (int i = 0 ; i<10 ; i++) {
    thread = new WorkerThread();
    thread.doStuff();
}

我的 WorkerThread 看起来像这样:

class WorkerThread {
    public void run() {
        ...
    }

    public void doStuff() {
        ...
    }
}

问题是,很明显,我从 run 方法调用 doStuff ,它与其他线程同时执行,但如果我直接从 main 调用 doStuff ,它不是同时执行的。

好的,现在的问题是:有没有一种方法可以同时执行 doStuff 方法,而不是从 run 方法调用它,而是从 main 方法调用它?

4

4 回答 4

2

您不能直接调用 Thread 对象上的方法。获得线程并发的唯一方法是调用它的 start() 方法,该方法又在单独的执行线程上调用 run()。直接从 main() 调用任何其他方法就像在常规非线程对象上调用方法一样;没有并发,没有什么特别的事情发生,方法立即执行。

听起来您正在尝试在主线程和工作线程之间进行通信。每个线程的 run() 方法负责在该线程上执行代码。如果您可以与该 run() 方法进行通信,那么您可以控制该线程上发生的事情。

一种方法是在构造线程时传入一个变量。保存 run() 方法可以检查以确定要执行的操作的值。例如,下面我们有一个枚举,其中包含三个可能的操作。run() 方法查看枚举并根据传递给 WorkerThread() 构造函数的值决定要做什么。

class WorkerThread {
    public enum Action { DO_STUFF, MAKE_WIDGETS, FROB_BARS }
    private Action action;

    public WorkerThread(Action action) {
        this.action = action;
    }

    public void run (){
        switch (action) {
            case DO_STUFF:     doStuff();     break;
            case MAKE_WIDGETS: makeWidgets(); break;
            case FROB_BARS:    frobBars();    break;
        }
    }

    public void doStuff()     { ... }
    public void makeWidgets() { ... }
    public void frobBars()    { ... }
}

现在我们的 main() 方法看起来像这样。您创建 WorkerThreads 并传入要执行的操作,然后调用 start()。

WorkerThread[] threads = new WorkerThread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new WorkerThread(WorkerThread.Action.DO_STUFF);
    threads[i].start();
}

你可以用无数种不同的方式做同样的事情。除了拥有一个 WorkerThread 类,您还可以拥有几个具有不同 run() 方法的不同类,然后从 main() 实例化适当的子类。

class DoStuffWorkerThread     extends Thread { ... }
class MakeWidgetsWorkerThread extends Thread { ... }
class FrobBarsWorkerThread    extends Thread { ... }

如果你愿意,你甚至可以在 main() 中创建匿名线程类。然后逻辑可以是任何 main() 想要的。

Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new Thread() {
        public void run() {
            doStuff();
        }
    };

    threads[i].start();
}
于 2012-12-02T16:49:44.783 回答
0

当您使用时, thread.doStuff();您没有使用线程,至于使用线程,您将不得不调用thread.start()方法,该方法将在内部调用run()方法。

于 2012-12-02T16:32:31.183 回答
0
 Thread[] threads = new Thread()[10];
    for (int i = 0 ; i<10 ; i++) {
        if ( i<5) {
          threads[i] = new Thread(new WorkerA());
        } else {
          threads[i] = new Thread(new WorkerB());
        }
        threads[i].start();
    }

起初,您正在创建一个数组,但没有正确使用它。您不能将对象分配给数组吗?然后你必须调用start()方法在后台执行线程并调用他的run方法。

你的工人应该是这样的:

class WorkerA implements Runnable {            

    public void run (){
        ...
        // put here your code from doStuff in one Version
        ...
    }

}

class WorkerB implements Runnable {

    public void run (){
        ...
        // put here your code from doStuff in an other Version
        ...
    }

}

thread[i].start()现在,您可以在引用数组的任何地方调用它,而不是在循环中调用它。

于 2012-12-02T16:37:59.603 回答
0

你可以使用Runnable它。

// Dictate what work needs to be done
Runnable work = new Work(); // or new OtherWork();

Thread thread = new Thread(work);
thread.start();

class Work implements Runnable {
    public void run(){
        System.out.println("do stuff");
    }
}

class OtherWork implements Runnable {
    public void run() {
        System.out.println(" do other stuff");
    }
}

编辑
建议使用线程池而不是为每个任务创建(和丢弃)线程。这是因为在创建/丢弃线程时有一些开销,而且它也使得管理任务应该在什么并发下完成等变得更容易。

无论如何,您可以使用Thread类自己创建线程池,但这需要大量工作,而且很难做到正确。相反,最好使用 JDK 中可用的现成解决方案。您可以按如下方式使用它:

ExecutorService threadPool = Executors.newFixedThreadPool(4);
threadPool.execute(new Work());
threadPool.execute(new OtherWork());

// After submitting all your task (or when your application wants to terminate)
// You should call shutdown() on the thread pool so that the JVM can exit
threadPool.shutdown();
于 2012-12-02T16:40:43.053 回答