Thread和Runnable区别

Thread本身是实现了Runnable接口的类。一个类只能有一个父类,但是却能实现多个接口,因此Runnable具有更好的扩展性。
重写Thread类的run方法和实现Runnable的run方法不同点就是Thread的run方法不可以共享,就是说A线程不能把B线程的run方法当做自己的执行单元。而Runnable可以。

记住一点:创建线程只有一种方式构造Thread类,而实现线程执行单元有2种方式:1.Thread#run   2.Runnable#run将实例化用于Thread构造器中

无论Thread#run还是Runnable#run都是想将线程的控制本身和业务逻辑的运行分开,达到职责分明、功能单一的原则。

Runnable#run并不是创建新线程,单独使用的情况下就是一个普通的执行单元。

Thread源码

标记1:判断如果当前线程是不是新建状态,如果不是则一定开启了start方法。这时候如果在调用一次start()会跑出异常。

标记2:start0才是真正创建新线程方法,这里就开始调用本地方法实现了并将该线程状态设置为true,如果为false则通知该线程组创建当前线程失败,回滚并重写其他尚未启动线程。

Runnable接口源码:

package java.lang;

@FunctionalInterface
public interface Runnable {
    void run();
}

Thread实现了Runnable#run。如果直接使用run方法实际就是调用一个普通的执行单元,并没有启动start0()。

示例:

public class Chapter01 {

    static class ThreadTicket extends Thread {
        private int ticket = 10;

        @Override
        public void run() {
                if (this.ticket > 0) {
                    System.out.println(this.getName() + " 卖票:ticket" + this.ticket--);
            }
        }
    }


    static class RunnableTicket implements Runnable {
        private int ticket = 100;

        @Override
        public void run() { 
                if (this.ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + " 卖票:ticket" + this.ticket--); 
            }
        }
    }


    public static void main(String[] args) {
        //使用Thread类
        IntStream.range(0, 3).forEach(t -> {
            new ThreadTicket().start();
        });
//
//        //Runnable 类
//        RunnableTicket ticket = new RunnableTicket();
//        IntStream.range(0, 10).forEach(t -> {
//            new Thread(ticket).start();
//        });

    }
}

使用Thread方式结果为:

Thread-0 卖票:ticket10
Thread-2 卖票:ticket10
Thread-2 卖票:ticket9
Thread-2 卖票:ticket8
Thread-1 卖票:ticket10
Thread-2 卖票:ticket7
Thread-0 卖票:ticket9
Thread-2 卖票:ticket6
Thread-1 卖票:ticket9
Thread-2 卖票:ticket5
Thread-0 卖票:ticket8
Thread-2 卖票:ticket4
Thread-2 卖票:ticket3
Thread-2 卖票:ticket2
Thread-2 卖票:ticket1
Thread-1 卖票:ticket8
Thread-1 卖票:ticket7
Thread-1 卖票:ticket6
Thread-1 卖票:ticket5
Thread-1 卖票:ticket4
Thread-1 卖票:ticket3
Thread-1 卖票:ticket2
Thread-1 卖票:ticket1
Thread-0 卖票:ticket7
Thread-0 卖票:ticket6
Thread-0 卖票:ticket5
Thread-0 卖票:ticket4
Thread-0 卖票:ticket3
Thread-0 卖票:ticket2
Thread-0 卖票:ticket1

Process finished with exit code 0

这里示例可以通过static修饰变量,但是在高并发下一样会出现重复售票。后面就需要使用线程安全这一块知识了(这里不提及)。

下面使用Runnable#run

   //Runnable 类
        RunnableTicket ticket = new RunnableTicket();
        IntStream.range(0, 10).forEach(t -> {
            new Thread(ticket).start();
        });

使用Runnable方式结果为:看并发下面虽然共享,但还是出现线程不安全问题。

Thread-0 卖票:ticket9
Thread-4 卖票:ticket7
Thread-5 卖票:ticket6
Thread-3 卖票:ticket8
Thread-9 卖票:ticket4
Thread-1 卖票:ticket10
Thread-2 卖票:ticket10
Thread-7 卖票:ticket2
Thread-8 卖票:ticket3
Thread-6 卖票:ticket5

到这里就结束了,希望大家对两种区别有很好的认识。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值