Java线程和run方法

时间:2012-12-02 16:27:02

标签: java multithreading

我正在编写一个使用某些线程的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 个答案:

答案 0 :(得分:2)

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

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

一种方法是在构造Thread时传入一个变量。保存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();
}

你可以用无数种方式做同样的事情。您可以使用不同的run()方法,而不是拥有一个WorkerThread类,然后从main()实例化相应的子类。

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

如果愿意,您甚至可以在main()内创建匿名Thread类。然后逻辑可以是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();
}

答案 1 :(得分:0)

当您使用thread.doStuff();时,您没有使用线程,因此要使用线程,您必须调用thread.start()方法,该方法将在内部内部调用run()方法。

答案 2 :(得分: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()

答案 3 :(得分: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();