目录

Thread 和 Runnable 的区别

对问题的疑惑

其实这个问题问的很奇怪,看到这个问题的瞬间,都会想到问的是:

new Thread(runnable).start() 和 runnable.run() 的区别?

可是

  • runnable.run() 明明就只是单纯地执行一个对象里面的方法,
  • thread.start()才是线程从新建到就绪的方法,此时线程等待CPU调度,得到资源才会去执行run()

这种问题很呆,所以我觉得应该不是问这个(=。=)

实现 Runnable 和继承 Thread 的区别?

我觉得这样问才是问题真正的问法,那我们看一下三段代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 继承 Thread 1
class MyThread extends Thread {
    public void run(){
        // TODO Auto-generated method stub
    }
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    new MyThread().start();
    new MyThread().start();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 继承 Thread 2
class MyThread extends Thread {
    public void run(){
        // TODO Auto-generated method stub
    }
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    MyThread mt = new MyThread();
    new MyThread(mt).start();
    new MyThread(mt).start();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 实现 Runnable
class MyRunnable implements Runnable {
    public void run(){
        // TODO Auto-generated method stub
    }
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    MyRunnable mr = new MyRunnable();
    new Thread(mr).start();
    new Thread(mr).start();
}

实际上在没有成员变量的情况下,三者的运行结果并无任何区别。

若是有成员变量,后两种写法会因为成员变量所在的对象只被实例化了一次而导致结果有所区别。当然,还有多线程必须要注意同步加锁的问题。这些与问题无关的这里就不展开说了。

看到网上很多都在说:

  1. 代码可以被多个线程复用,增加程序的健壮性;
    • 我想说的是, 难道继承就不能复用代码了吗? (3 段代码的两个线程都是执行同一个run()方法)
  2. 适合多个相同的程序代码的线程去处理同一个资源(即线程资源共享);
    • 我想说的是, 难道继承就不能共享了吗? (第 2 段代码)
  3. 可以避免 Java 中的单继承的限制;
    • 我想说的是……这点没的说,确实可以避免~

简单分析 Thread 源码

嗯,本章只是很简单的看一下 Thread 的头部,不深入分析~

1
2
3
4
5
6
7
8
public
class Thread implements Runnable {
    // ...
    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    // ...
}

可见,Thread 也实现了 Runnable 接口,只是提供了更多的可用方法和成员而已。

结论

综上所述,Thread 和 Runnable 的实质是继承关系,没有可比性。

事实是,Thread 和 Runnable 没有本质的区别,区别只是在用法上需不需要多继承以及是否有执行复杂线程操作的需求。


参考链接: