“实现Runnable”与“扩展线程”

从我在Java中使用线程的时间开始,我发现了这两种编写线程的方法:

使用可运行的implements Runnable

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

或者,通过extends Thread

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

这两个代码块有什么重大区别?


是的:实现Runnable是实现它的首选方法,IMO。 你并没有真正专注于线程的行为。 你只是给它一些东西来运行。 这意味着构图是哲学上“更纯粹”的方式。

实际上,这意味着您可以实现Runnable并从另一个类扩展。


tl; dr:实现Runnable更好。 但是,警告很重要

一般来说,我会推荐使用类似于Runnable东西而不是Thread因为它可以让你的工作只与你的并发选择松散结合。 例如,如果您使用Runnable并稍后决定这实际上并不需要它自己的Thread ,则可以调用threadA.run()。

警告:在这里,我强烈建议不要使用原始线程。 我更喜欢使用Callables和FutureTasks(从javadoc:“可取消的异步计算”)。 超时,适当的取消和现代并发支持的线程池的集成对于我来说比成堆的原始线程更有用。

后续:有一个FutureTask构造函数,允许您使用Runnables(如果这是您最熟悉的),并且仍然可以从现代并发工具中受益。 引用javadoc:

如果您不需要特定的结果,请考虑使用表单的结构:

Future<?> f = new FutureTask<Object>(runnable, null)

所以,如果我们用你的threadA替换它们的runnable ,我们得到以下结果:

new FutureTask<Object>(threadA, null)

另一个允许您更接近Runnables的选项是ThreadPoolExecutor。 您可以使用execute方法来传递Runnable来执行“将来某个时候给定的任务”。

如果你想尝试使用线程池,上面的代码片段将变成如下所示(使用Executors.newCachedThreadPool()工厂方法):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

故事的道德启示:

只有在您想覆盖某些行为时才继承。

或者应该将其理解为:

继承少,接口多。

链接地址: http://www.djcxy.com/p/2683.html

上一篇: "implements Runnable" vs. "extends Thread"

下一篇: Java inner class and static nested class