Java中Runnable和Thread的区别

很多时候我们都知道在Java中创建线程类的方式有最常见的两种:

  1. 实现Runnable接口
  2. 继承Thread类

其实我也是这样认为的直到有一天无意中看到了Runnable和Thread源码,才真正明白了其中的道理。
Runnable源码:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

源码中对于run()方法的解释是:当使用实现Runnable接口的对象创建线程时,启动线程会导致在单独执行的线程中调用对象的 run 方法。

Thread源码:

public class Thread implements Runnable {
    ...
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
	...	
}

其实看到这个源码就已经明白了,Runnable接口里面就真是只是一个接口,里面有一个抽象方法run()等着被重写,再看看那Thread类居然是实现了Runnable接口,覆盖了run方法,说白了Thread也是实现了Runnable接口。

下面看看用户自定义线程类:
1.继承Thread类


class TestThread1 extends  Thread {
    public void run(){
        System.out.println(Thread.currentThread().getName()+"\t <TestThread1> is ok");
    }
}

2.实现Runnable接口

class TestThread2 implements  Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"\t <TestThread2> is ok");
    }
}

启动方式:
1.继承Thread类
用户自定义线程类可以作为Thread类的构造参数,也可以直接new 然后调用start()启动线程,为何可以这样顺畅?因为Thread类的构造方法:
public Thread(Runnable target) {}
这个构造方法中的参数类型是一个Runnable接口类型的,而TestThread1是Thead的子类,自然也是相当与实现了Runnalbe接口的,因此这里可以作为Thread的构造参数的。

因为TestThread1是Thread的子类,因此可以直接创建TestThread1的子类,然后调用start()启动线程。

Thread t = new Thread(new TestThread1());
t.start();

TestThread1 t3 = new TestThread1();
t3.start();

运行结果:

Thread-1	 <TestThread1> is ok
Thread-2	 <TestThread1> is ok

2.实现Runnable接口

Thread t2 = new Thread(new TestThread2() );
t2.start();

这种方式创建的线程类,只能是实例化之后作为Thread类的构造参数,然后调用Thread类的stat()方式启动线程。

两种方式创建线程其实本质是相同的, 但是从实际的应用角度来讲,只要是创建线程类绝大多数是以实现Runnable接口为主的方式,好处有2:
1、避免继承的局限,一个类可以继承多个接口。
2、适合于资源的共享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值