我有一个名为MyThread
的类,它扩展了Thread类并实现了run()
函数。当我想运行它时,我有两种方法:
new MyThread().start()
(new Thread(new MyThread)).start();
任何人都可以区别对待吗?
答案 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#join
和foo
都提供了thread
;哪个是正确的? (答案是:thread
上的那个,但它令人困惑,所以最好不要这样做。)
答案 1 :(得分:4)
嗯,你有两种实现多线程的方法。
延长Thread
并使用new MyThreand().start()
开始您的主题。
实现Runnable
接口。在这种情况下,您可以使用(new Thread(new MyThread)).start()
;开始一个帖子。
有关详细信息,请参阅oracle official doc.
答案 2 :(得分:1)
您传递的MyThread
实例仅作为Runnable
,而不是单独的主题。
两种方式基本上没有区别:
Thread
在start()
内部执行的操作是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
创建新执行线程的两种方法:
首先要声明一个类(即@Override
public void run() {
if (target != null) {
target.run();
}
}
)是PThread
:Thread
的子类,并且应该覆盖PThread extends PThread
run
方法1}}线程。然后,我们可以轻松地创建此类的实例化并在其上调用class
:
start()
第二个是声明一个实现PThread pThread = new PThread(args);
pThread.start();
接口的类:Runnable
然后实现RThread implements Runnable
方法。我们必须实例化run
并将其作为RThread
目标传递给Thread
实例:
Runnable
正如您从上面的方式看到启动一个线程,实际上允许将 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 interface
或Runnable
或任何其他方式执行的任务。因此Thread
与Executors
的任务逻辑分离是一个很好的设计决策。
Executors
,通过多线程让生活更轻松,接受Runnable
作为任务。
<强>参考:强>
答案 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