这两种启动线程的方式有什么区别?

时间:2009-08-12 06:20:36

标签: java concurrency multithreading

如果我有一个实现Runnable接口的类,那么main方法中这些语句之间有什么区别?

MyThread t1 = new MyThread();
t1.start();

MyThread t2 = new MyThread();
new Thread(t2).start();

8 个答案:

答案 0 :(得分:1)

由于你做了t1.start(),我假设MyThread扩展了Thread。在这种情况下,第一个是正确的。

第二个创建一个新线程,然后在另一个线程中启动该任务。一个线程被浪费了。

答案 1 :(得分:1)

要在Java中实现一个线程,你基本上有两个选择。一:扩展Thread类并实现方法run。你的例子似乎就是这种情况。在这种情况下,您应该调用Thread.class的start()方法。这是你提供的两种变体之一。

第二个变体是您实现Runnable接口。在这种情况下,您还实现了方法run,但是您的类没有start,因此您使用Runnable作为参数创建一个新的Thread类(就像您在第二个示例中所做的那样)。但是,如果你已经扩展了Thread,那就没有意义了。

我个人更喜欢实现Runnable,因为我不会改变Thread的行为(可能会扩展它),但只使用Thread-functions。

答案 2 :(得分:1)

假设

class MyThread extends Thread

您的第一个电话会在新主题中启动您的代码。

电话

new Thread(new MyThread()).start();

也会在MyThread中运行你的代码,因为Thread构造函数只需要一个实现Runnable接口和run()方法的对象。你的MyThread类已经有了这个方法,所以它将由简单的包装器线程执行。另请注意,您的新MyThread基本上仍然是一个未启动的线程。

您可以尝试以下小程序:

public class MyThread extends Thread {
    public void run() {
        if (Thread.currentThread() != this) {
            System.out.println("Wrapped into a separate thread");
            start();
        } else {
            System.out.println("MyThread run as expected");
        }
    }
    public static void main(String[] args) {
        new Thread(new MyThread ()).start();
    }
}        

为了减少混淆,由于名称让我们看看另一个例子:

public class MyJPanel extends JPanel implements Runnable {
    public void run() {
        System.out.println("Hello MyJPanel");
    }
    public static void main(String[] args) {
        new Thread(new MyJPanel()).start();
    }
}

答案 3 :(得分:0)

第一个调用(如果它是run())将在当前Thread中执行,而第二个调用将创建一个新线程来运行Runnable的run()方法。

答案 4 :(得分:0)

在第二个中你创建一个你不在变量中保存的新线程并启动这个新线程。 t2保持不变。

在第一个创建t1并开始......

我认为,其次是毫无意义的

答案 5 :(得分:0)

每当您的类必须扩展另一个类时,请使用Runnable。

Runnable接口只包含run方法无法启动。

答案 6 :(得分:0)

假设MyThread仅实现Runnable接口,则第二个代码段是要使用的正确模式。 Thread.start()链接到一个本地方法,它将启动一个新线程。然后它会调用自己的run(),它会在其实例run()变量上调用Runnable。在您的第二个代码段中,这将是MyThread的实例,即Runnable

根据您提供的信息,第一个代码段将无法编译,除非:

  • 您已自行实施start方法。如果是这种情况,您的代码将不会启动新线程,您只会按照MyThread.start()中定义的当前线程中的流程进行操作。
  • 您实际上已扩展Thread以及实施Runnable。如果是这种情况,则Runnable接口是冗余的,因为Thread也实现了此接口。此外,如果要覆盖start方法,则应该小心,因为如果要打开新线程,则需要调用super。至少出于这个原因,最好只有一个类实现Runnable而不是执行Thread。此外,如果您只是实施Runnable,最好不要在名称中使用Thread这个词。

答案 7 :(得分:0)

  

MyThread t1 = new MyThread(); t1.start();

将是编译时异常

  

MyThread t2 = new MyThread(); new Thread(t2).start();

将正常工作.runnable接口没有启动方法。