我正在尝试在 Java 中学习多线程。我们使用两种方法来创建线程,第一种是通过扩展 Thread 类,第二种方法是通过实现 Runnable 接口。
在下面的示例中,我通过实现 Runnable 接口创建了一个线程。
class ThreadExample implements Runnable {
@Override
public void run() {
System.out.println("run method is called by thread named " + Thread.currentThread().getName());
System.out.println("run method is ending for thread named " + Thread.currentThread().getName());
}
}
public class TestInterruptingThread2 extends Thread {
public static void main(String args[]) {
ThreadExample threadExample = new ThreadExample();
Thread thread = new Thread(threadExample);
thread.start();
}
}
输出是 -
run method is called by thread named Thread-0
run method is ending for thread named Thread-0
如上例所示,要创建 ThreadExample 类的线程,我们首先创建它的对象,然后将其传递给Thread类的构造函数。
我的问题是,run()方法完成后,Thread类的实例传递给哪个ThreadExample类对象的对象会发生什么。它是否有资格进行垃圾收集?
以及如何通过实现 Runnable 接口创建线程比扩展 Thread 类更节省内存?
它是否有资格进行垃圾收集?
是的。当一个Thread
实例终止并且一旦对该对象的所有其他引用都丢失了,它将变得不可访问并且将成为垃圾回收的候选对象。
请注意,线程的堆栈通常会在垃圾收集器运行之前被回收。(它由线程的终止触发。)
如何通过实现
Runnable
接口创建线程比扩展Thread
类更节省内存?
这不是真正的问题。
该性能涉及对不延长理由Thread
的事实,创建和启动A派生Thread
或派生类Thread
是昂贵的。(在某些平台上,可能需要一毫秒的时间!)因此您希望避免重复创建新Thread
对象。
执行此操作的标准方法是使用线程池或ExecutorService
. 这些通过将任务封装为 a Runnable
(或 a Callable
) 并将其传递给长时间运行的工作线程/池线程来工作。这样的线程通常会在其生命周期内处理大量这些任务(一次一个),因此创建线程的成本会在多个任务上分摊……并且变得微不足道。
这与new Thread(Runnable)
vs 有extends Thread
什么关系?
在前一种情况下,您已经将您的任务封装为一个Runnable
,因此将您的应用程序转换为使用线程池/执行器相对简单。相比之下,如果您进行扩展,则Thread
必须更改明显更多的代码。
现在......您可以为您的自定义线程类实现一个线程池。然而,典型的线程池实现有一些复杂的逻辑和线程安全问题,所以这是一个坏主意。
扩展Thread
也是一个坏主意还有其他原因。但是您只是询问与性能相关的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句