java多线程之继承Thread类和实现Runnable接口的区别

1)java要完成多线程的创建有四种方式:

①继承Thread类,重写run方法

②实现Runnable接口,重写run方法

③通过线程池创建线程

④实现Callable接口,该接口被重写的方法带有返回值,异常信息等

这里我只讲继承Thread类和实现Runnable接口的区别

2)那么这两种创建多线程的方式到底有哪些不同呢,顾名思义,一个是继承一个是实现。

众所周知,java本质上其实是单继承的,举个例子。现在有两个类,Dog和Cat,按照面向对象的思想,我们可以将这两个类的共性抽取出来,抽取出来的类就是抽象类,那么Dog和Cat肯定要继承这个抽象类的,不然抽象类的存在就没有意义了。代码如下


    

看到这里,想必会有初学者会感到疑惑,既然父类方法体都不具体,还要子类自己去写,那为什么还要抽取父类再来继承它呢。那么这里就涉及到了多态,对多态的应用还不理解的朋友可以去多看看书。

3)那么现在给出一个场景,如果Dog和Cat不只一个呢。我们难道要去创建多个Dog和Cat类吗,很显然这里用到了多线程。那么创建多线程是继承Thread还剩实现Runable接口呢,显然,这里继承Thread是不合适的,因为Dog和Cat已经存在需要继承的父类了,不能再去继承其他类了。所以,这种情况就可以去实现Runnable接口来创建多线程。

4)说完了继承Thread的局限性,其实他们之间还有一个巨大的区别,那就是的问题。这里我写一个案例你们就明白了。代码如下:

下面是结果:

 

可以看到,加了synchronized 同步关键字之后,线程还是出现了安全问题。这是为什么呢?

显然,这肯定是锁的问题。那么被5同步方法修饰的锁对象到底是什么呢,答案是this

测试一下: 

结果如下:

可以看到,线程依旧存在安全问题,说明锁默认就是this,那么为什么this锁再这里不行呢。这里就考你面向对象学的怎么样了,如下:

因为你创建了两个线程类对象,所以当t1.start()和t2.start()后去找run方法时,this是不一样的,this分别代表t1和t2。你想想,锁都不一样了,何来同步。

解决方案:这里使用类锁,且类一样

结果如下:

 

可以看到,在当前线程没有执行完同步代码块时,另外的线程是进不来的。

 

 5)接下来我们看实现Runnable接口来创建多线程有何不同

这里没有加任何同步,出现了安全问题,结果如下

 

 解决方案:我们给run方法加上同步关键字

结果如下:

 

安全问题等到解决。

那么看到这里就会有人疑惑,难道这个同步锁默认是类锁吗。其实不是,就是this锁,为什么this锁可以呢?看下面:

 

 因为我这里只创建了一个My1对象,t1和t2共用一个My1对象,my1只有一个,所有以this只能是my1。锁都一样了,还怕同步不了吗。

6)总结:继承Thread实现多线程需要造多个源对象,此时需要同步最好不好用this锁,当然具体情况具体分析。而且当前类不能再继承其他对象了。所以,以后在写代码完成某些需求要使用多线程时,尽量不要继承Thread类。最好是用实现Runable来创建多线程。

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值