简体   繁体   English

Java线程和run方法

[英]Java thread and the run method

I'm writing a Java application that uses some threads.我正在编写一个使用一些线程的 Java 应用程序。 Main method looks like this:主要方法如下所示:

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

and my WorkerThread looks like this:我的 WorkerThread 看起来像这样:

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

    public void doStuff() {
        ...
    }
}

The matter is that, obviousely, I call doStuff from the run method it is executed like concurrently with other threads, but if i call doStuff directly from the main it is executid not cocurrently.问题是,很明显,我从 run 方法调用 doStuff,它像与其他线程一样同时执行,但如果我直接从 main 调用 doStuff,它不会同时执行。

Ok, now the question is: is there a way to execute, concurrently, the doStuff method calling it not from the run method, but rather, from the main?好的,现在的问题是:有没有办法同时执行 doStuff 方法,而不是从 run 方法调用它,而是从 main 调用它?

You cannot directly call methods on a Thread object.您不能直接调用 Thread 对象上的方法。 The only way to get concurrency with a Thread is to invoke its start() method, which in turn calls run() on a separate thread of execution.获得线程并发的唯一方法是调用它的 start() 方法,该方法又在单独的执行线程上调用 run()。 Calling any other methods directly from main() is just like calling methods on regular non-Thread objects;直接从 main() 调用任何其他方法就像在常规非 Thread 对象上调用方法一样; there's no concurrency, nothing special happens, the methods execute immediately.没有并发,没有什么特别的事情发生,方法立即执行。

It sounds like you're trying to communicate between the main thread and the worker threads.听起来您正在尝试在主线程和工作线程之间进行通信。 Each thread's run() method is in charge of executing code on that thread.每个线程的 run() 方法负责在该线程上执行代码。 If you can communicate with that run() method then you can control what happens on that thread.如果您可以与该 run() 方法进行通信,那么您就可以控制该线程上发生的事情。

One way to do that is to pass a variable in when you construct the Thread.一种方法是在构造线程时传入一个变量。 Save a value that the run() method can examine to determine what to do.保存 run() 方法可以检查以确定要执行的操作的值。 For example, below we have an enum that has three possible actions in it.例如,下面我们有一个枚举,其中包含三个可能的操作。 The run() method looks at the enum and decides what to do based on the value that was passed to the WorkerThread() constructor. 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()    { ... }
}

Now our main() method looks like this.现在我们的 main() 方法看起来像这样。 You create WorkerThreads passing in the action to perform, then call start().您创建传递要执行的操作的 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();
}

You could do the same thing in myriad different ways.你可以用无数种不同的方式做同样的事情。 Instead of having one WorkerThread class you could have several different classes with differing run() methods and then instantiate the appropriate sub-class from main().您可以拥有多个具有不同 run() 方法的不同类,而不是只有一个 WorkerThread 类,然后从 main() 实例化适当的子类。

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

You can even create anonymous Thread classes right inside main(), if you like.如果愿意,您甚至可以直接在 main() 中创建匿名线程类。 Then the logic can be whatever main() wants.然后逻辑可以是 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();
}

When you are using thread.doStuff();当你使用thread.doStuff(); you are not using Threading, as to use threading you will have to call thread.start() method, which will internally call run() method internally.您没有使用线程,因为要使用线程,您必须调用thread.start()方法,该方法将在内部调用run()方法。

 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();
    }

At first, you're creating an array but don't use it right.起初,您正在创建一个数组,但没有正确使用它。 You can not assign a Object to an array?你不能将一个对象分配给一个数组? Then you have to call the start() method to execute the thread in background and invoke his run method.然后你必须调用start()方法在后台执行线程并调用他的 run 方法。

Your Worker's should look like this:您的 Worker 应如下所示:

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

}

Instead of calling the thread[i].start() in your loop, you can now call it anywhere with the reference to your array.您现在可以使用对数组的引用在任何地方调用它,而不是在循环中调用thread[i].start()

You can use Runnable for that.您可以为此使用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");
    }
}

EDIT :编辑
It is recommendable to use thread pools instead of creating (and discarding) threads for each task.建议使用线程池而不是为每个任务创建(和丢弃)线程。 This is because there is some overhead in creating/discarding threads, and it also makes it easier to manage at what concurrency the tasks should be done etc.这是因为在创建/丢弃线程时存在一些开销,并且还可以更轻松地管理任务应该以何种并发执行等。

Anyways, you could create your thread pool by yourself using Thread class, but that's a lot of work and it's hard to get it right.无论如何,您可以使用Thread类自己创建线程池,但这需要大量工作,而且很难做到正确。 Instead, it's best to use the ready made solution available in the JDK.相反,最好使用 JDK 中提供的现成解决方案。 You can use it as follows:您可以按如下方式使用它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM