直接调用run方法是不好的做法

时间:2014-04-28 06:17:03

标签: java multithreading

大多数时候我想在一个新线程中运行一段代码,它会耗费一些时间,但在某些情况下我想用调用方法的线程运行它。直接调用run方法是不好的做法吗?

如果不是一个好主意,最好将代码放在另一个可以被新线程调用或复制代码的方法中吗?

这是一些示例代码,它只是为了说明我想要实现的目标:

class Main {
    public Main() {
        new Thread(new WorkerThread(1, 2)).start(); // This is what I'd do if I wanted it to run in a new thread.
        new WorkerThread(1, 2).run(); // Is it bad practice to do this?
    }
}

class WorkerThread implements Runnable {
    private int int1, int2;

    public WorkerThread(int int1, int int2) {
        this.int1 = int1;
        this.int2 = int2;
    }

    public void run() {
        // Do something time consuming with the ints.
    }
}

6 个答案:

答案 0 :(得分:4)

调用run同步执行代码;而run方法将允许代码异步执行。

在需要避免线程的测试场景中,直接调用run通常是有益的。

答案 1 :(得分:3)

您可以直接调用run方法,但这将在您当前的线程中执行。不会创建额外的线程。然而,调用“start”将创建一个新线程并在内部调用run方法。

因此,如果您正在寻找线程创建,则需要使用start方法。

更多详情here

答案 2 :(得分:2)

在现在过时的Java Blackberry API中,Runnable的实现用于各种事物,例如definition of GUI callbacks。接口Runnable可以看作是面向对象的定义函数指针的方式,因此Runnable和多线程首先是正交概念。

答案 3 :(得分:2)

一个好主意是使用Extract Method(重构技术)来提取需要直接运行的run方法的部分(可能是全部)。

class Worker implements Runnable {
    private int int1, int2;

    public Worker(int int1, int int2) {
        this.int1 = int1;
        this.int2 = int2;
    }

    public void work() {
        ...
    } 

    public void run() {
        work();
    }
}

然后

new Thread(new WorkerThread(1, 2)).start(); 
new WorkerThread(1, 2).work(); // Looks good!

答案 4 :(得分:2)

我知道已经有很多其他答案,但你的问题是关于"练习",而且这个词没有出现在其中任何一个。

什么是良好的做法是编写易于其他人理解的代码,并且最好在没有任何内联评论的情况下易于理解。

只要" run"的含义,调用foobar.run()就没有错。对于阅读你的课程的人来说,这是显而易见的。

您的班级名为WorkerThread,即使不是一个帖子。这可能会让人感到困惑。并且调用workerThread.run()可能会更加混淆他们是否涉及线程。

我想说,如果有意义的话,继续调用run()方法,但是改变类,以便读者知道你没有尝试启动一个线程并以错误的方式执行它。

答案 5 :(得分:1)

直接调用run()的{​​{1}}方法没有任何问题。

在Java 1.4和1.5的早期版本中(不可否认是由于某个错误),如果您创建Runnable但不继续调用其Thread方法可能会出现问题,因为资源是分配的,永远不会释放。

请参阅Why is my Java program leaking memory when I call run() on a Thread object?

您的代码可以避免这种情况 - 您拨打start()的对象不是run()。如果你这样做了:

Thread

...然后在有缺陷的JVM中,分配给 class WorkerThread extends Thread { public void run() { ... } } ... public void main() { WorkerThread a = new WorkerThread(); WorkerThread b = new WorkerThread(); a.start // runs parallel to main thread b.run(); // runs in main thread } 的资源不会被清除。

您应该让JVM错误(在您可能没有定位的版本上)影响您的编码风格并不明显。但是,很明显,代码错误地表明了它的意图。我们不打算在单独的线程中运行此代码,因此我们不应将其声明为线程。 b样式(已使用)的引入使得只有创建new Thread(Runnable x)才能轻松创建Threads

我对您的代码的唯一建议是更改WorkerThread的名称 - 因为它并不总是一个帖子。 Worker将是一个很好的通用名称。在实际代码中,你会给它一个名称,表明它的工作类型!

new Thread(new Worker(1, 2)).start();
new Worker(1, 2).run(); 

正如已经注意到的那样 - 除了包装在一个线程中之外,还有Runnable的用法。这两个概念没有紧密结合。