启动线程的不同方法有什么区别?

时间:2013-11-26 08:05:24

标签: java multithreading

我有一个名为MyThread的类,它扩展了Thread类并实现了run()函数。当我想运行它时,我有两种方法:

  1. 新建一个实例并调用该函数,例如:new MyThread().start()
  2. new a instance并将实例作为参数传递给Thread的构造函数,然后调用Thread的start函数。像这样:(new Thread(new MyThread)).start();
  3. 任何人都可以区别对待吗?

8 个答案:

答案 0 :(得分:19)

因为你说过你的课扩展 Thread,所以第二个有点多余。在第二个示例中,您没有将自己的课程用作Thread,而只是将其用作Runnable

通常情况下,您要么延长Thread,然后调用自己的start(您的#1),您要实施Runnable,然后使用Thread来运行它(你的#2)。但是你不会扩展Thread然后使用另一个Thread来运行它。

就不同之处而言,如果您需要做任何事情来控制或询问线程,在第一种情况下,您将在 类的实例上使用Thread方法;在第二种情况下,您将在使用new Thread创建的实例上使用它们。如果您扩展Thread但是通过#2运行它,则您实例上的Thread方法无关紧要,可能会造成混淆。

最后一点可能更清楚,例如:

扩展Thread

的示例
class Foo extends Thread {
    public void run() {
        // ...
    }
}

// Create it
Foo foo = new Foo();

// Start it
foo.start();

// Wait for it to finish (for example)
foo.join();

注意我们已经开始并通过foo引用加入了该主题。

实施Runnable

的示例
class Foo implements Runnable {
    public void run() {
        // ...
    }
}

// Create it
Foo foo = new Foo();

// Create a Thread to run it
Thread thread = new Thread(foo);

// Start it
thread.start();

// Wait for it to finish (for example)
thread.join();

注意我们已经开始并通过thread引用加入了该主题。

不要这样做:

class Foo extends Thread {
    public void run() {
        // ...
    }
}

// Create it
Foo foo = new Foo();

// Create a Thread to run it -- DON'T do this
Thread thread = new Thread(foo);

// Start it
thread.start();

...因为现在Thread#joinfoo都提供了thread;哪个是正确的? (答案是:thread上的那个,但它令人困惑,所以最好不要这样做。)

答案 1 :(得分:4)

嗯,你有两种实现多线程的方法。

  1. 延长Thread并使用new MyThreand().start()开始您的主题。

  2. 实现Runnable接口。在这种情况下,您可以使用(new Thread(new MyThread)).start();开始一个帖子。

  3. 有关详细信息,请参阅oracle official doc.

答案 2 :(得分:1)

您传递的MyThread实例仅作为Runnable,而不是单独的主题。

两种方式基本上没有区别

Threadstart()内部执行的操作是run()调用Runnable方法。

当您执行new Thread(new MyThread()).start()时,由于Thread本身实现Runnable,您只是多余。

但由于新线程将调用run()的{​​{1}}方法,因此逻辑上没有任何区别。

答案 3 :(得分:1)

你不应该这样做。创建一个线程确实会改变一些变量,比如ThreadGroup中的“未启动线程数”。

虽然它不应该导致问题,但它的风格很糟糕并会让人迷惑(“为什么他这样做?必须是一个很好的理由!”)。

答案 4 :(得分:1)

如果您的课程本身延伸Thread,您可以按照第一种方式:

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

如果您查看JavaDoc,您会看到第二种方式是针对(仅)实施Runnable的类(这意味着您的班级只需要实现run()方法)。

public class MyClass implements Runnable {
     public void run() { ... }
}

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

区别在于Runnable只是一个界面而Thread是一个类。这意味着如果你想让你的逻辑作为一个类的一部分,由于某种原因需要扩展一个不同的类,那么你仍然可以实现Runnable并使用第二种方式。

答案 5 :(得分:1)

线程本身是Runnable的实现。当创建Thread的实例并启动它时,它将执行它自己的run()方法。如果非null Runnable target被赋予它的构造函数,那么它将调用它的目标run()方法,这从{{1}的实现run()方法可以看出class:

Thread

创建新执行线程的两种方法:

  1. 首先要声明一个类(即@Override public void run() { if (target != null) { target.run(); } } )是PThreadThread的子类,并且应该覆盖PThread extends PThread run方法1}}线程。然后,我们可以轻松地创建此类的实例化并在其上调用class

    start()
  2. 第二个是声明一个实现PThread pThread = new PThread(args); pThread.start(); 接口的类:Runnable然后实现RThread implements Runnable方法。我们必须实例化run并将其作为RThread目标传递给Thread实例:

    Runnable
  3. 正如您从上面的方式看到启动一个线程,实际上允许将 RunThread rThread = new RunThread(args); // args constructor argument if required Thread t = new Thread(rThread); t.start(); 扩展的类(如Thread)传递给新的PThread构造函数启动它的Thread目标。因为Runnable本身是Thread的实现。

    Runnable

    但这种操作是不必要的,或者你不应该这样做。由于 PThread pThread = new PThread(args); Thread t = new Thread(pThread); // allowed as pThread is extending Thread and hence, //an implementation of Runnable t.start(); 已经是pThread,我们可以致电Thread来执行pThread.start()方法,这是run()的核心。创建另一个线程只是为了执行Thread只是额外的开销,因为除了执行pThread的{​​{1}}方法之外它不会做任何事情。

    但是,您根本不应该使用pThread的扩展名。因为,

    实现Runnable总是优于扩展线程:

    • 继承所有线程方法只是用于表示可以使用run()轻松完成的任务的额外开销。

    • Thread实现到类仍允许我们在必要时将其扩展到其他类。

    • 在OOP中,扩展类通常意味着添加新功能,修改或改进行为。如果我们不对Runnable进行任何修改或更改其行为,请改为使用Runnable

    • Thread接口表示可由普通Runnable interfaceRunnable或任何其他方式执行的任务。因此ThreadExecutors的任务逻辑分离是一个很好的设计决策。

    • Executors,通过多线程让生活更轻松,接受Runnable作为任务。

    <强>参考:

    1. Class Thread
    2. Difference between Thread class and Runnable interface

答案 6 :(得分:0)

(new Thread(new MyThread))。start();

每个Thread实现Runnable;在这种情况下,MyThread实例用作Runnable,新线程调用MyThread实现的run方法。您将无法使用MyThread停止线程(或通过任何方式控制它)。

答案 7 :(得分:0)

启动线程(class implementing Runnable or extending Thread class)

的方式完全没有区别

这只是你应用的抽象,请注意(Runnable object, is more general, because the Runnable object can subclass a class other than Thread) 良好的编码实践。

In both of the cases Thread.start() will called