为什么应该使用Runnable而不是Thread?

7

我刚刚学习了与线程相关的理论知识,其中有线程和可运行接口(Thread和Runnable)。

class A extends Thread{
    public void run(){
            while(true) {
                System.out.println("Hi");
            }           
        }
    }

class B implements Runnable{
    public void run(){
        System.out.println("Hi");
    }
}

Thread具有丰富的API,那么为什么我要使用Runnable而不是Thread呢?

谢谢。

2个回答

13
  1. Java不支持多继承,这意味着你只能扩展一个Java类,所以一旦你扩展了Thread类,你就失去了机会,无法在Java中再继承(扩展)另一个类。

  2. 在面向对象编程中,扩展一个类通常意味着添加新功能、修改或改进行为。如果你没有对Thread进行任何修改,则应该使用Runnable接口。

  3. 实现Runnable使得你的类更加灵活(可以实现多个接口)。


在什么情况下,您想同时实现Runnable并扩展其他内容?(而超类是无法扩展Thread本身的) - user253751
谢谢您的回复。如果我们需要在类中拥有JFrame的特性,那么我们就必须扩展JFrame来获得它。在同一个类中,如果我们需要获取线程(并发处理)的特性,我们就必须实现Runnable接口。因为我们不能继承Thread(我们已经继承了一个类)。希望您能理解。@immibis :) - Dhanuka
大多数人会建议不要扩展JFrame,原因与不应该扩展Thread的原因相同。所以你可以决定这些是否是好的理由 :) - user253751
是的!你说得对。感谢@immibis指出这一点。我会记住的。 - Dhanuka

4
其中一个重要的优点是:你不必在新线程上运行Runnable。
有一天,您可能决定不再在新线程上运行它,而是直接(在当前线程)或在线程池上运行它,然后您可以将new Thread(runnable).start()更改为threadPool.submit(runnable)或runnable.run() - 变化只影响一个地方。
此外,如果让Runnable挂起,它就不会浪费资源-它不计入线程限制(如果有),也不保留堆栈空间。假设您想按顺序执行一次性任务队列中的每个任务-当然,您可以拥有一个Queue,并在上一个完成后启动每个线程,但这样会浪费许多内存用于非运行线程。如果您使用Runnable队列,则仅在实际运行时使用较少的内存。

线程是“工人”,而Runnable是“一些工作”。当然,你可以有一堆只做一件事情的工人,但那样效率很低,不是吗? - user253751

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接