黑马程序员技术交流社区

标题: 多线程中的Runnable和Thread 的区别。 [打印本页]

作者: wangning9130    时间: 2013-9-16 17:31
标题: 多线程中的Runnable和Thread 的区别。
关于多线程有两种方式,这个大家都很清楚。一个是通过实现Runnable接口,另一个是继承Thread类。通过实现Runnable接口来实现可以避免java单继承的问题。
可是,今天看毕老师视频。其中说到卖票的地方,就有些不明白了。四个窗口一块卖票。一共一百张。
为什么用实现runnable的方式就能实现是个线程一共卖一百张呢?
而另一中就不行呢?

作者: 酱爆    时间: 2013-9-16 17:53
两种都可以实现卖票程序,只是Thread是继承关系,runnable是接口,如果你先前已经继承了一个类,你就不能再继承Thread了(java单继承),所以你可以实现Runnable接口,这要看实际应用吧。。不知道说的对不对
作者: 周文斌    时间: 2013-9-16 18:28
哈哈,同学问的好,我前几天刚写了一篇关于接口的文章,里面就是拿Runnable接口和Thread类做的例子。

http://tdtdtq.blog.163.com/blog/static/2256531472013815119286/?newFollowBlog

下面我来给你讲讲为什么实现Runnable接口能做到四个窗口公卖一百张,而继承Thread类不可以。
  1. class ChildThread extends Thread{
  2.         private int count=100;
  3.         run(){
  4.                 System.out.println(count--);
  5.         };
  6. }

  7. public class Test{
  8.         public static void main(String[] args){
  9.                 new ChildThread().start();
  10.                 new ChildThread().start();
  11.                 new ChildThread().start();
  12.                 new ChildThread().start();
  13.         }
  14. }
复制代码
上面这个例子 就是 用继承Thread类,覆盖了run()方法做的。可以看到,在内存中每个ChildThread对象都有自己的内存空间,当JVM调用run()方法操作count成员时,实际上大家操作的都是自己的count~其实这就是各卖各的票了,为了让四个线程都操作一个count,我们可以将count静态化(当然这不是最优选)。

下面要说的是实现Runnable接口的方式做。

  1. Runnable R=new Runnable(){
  2.         run(){
  3.                 .....
  4.         }
  5. }
  6. new Thread( R ).start();
  7. new Thread( R ).start();
  8. new Thread( R ).start();
  9. new Thread( R ).start();
复制代码
大家应该都知道,咱们之前复写Thread类的run()方法是用于给JVM调用的,也就是说Runnable接口方式也是用了某种技巧,让Thread类的run()方法调用到我们在实现Runnable接口时覆盖的run方法!

嗯~下面我们只需要追踪源代码即可。
  1. public class Thread implements Runnable {
  2.         ...
  3.         //定义了一个Runnable的对象
  4.         private Runnable target;
  5.         ...
  6.         public Thread(Runnable target) {
  7.                 init(null, target, "Thread-" + nextThreadNum(), 0);
  8.         }
  9.         private void init(ThreadGroup g, Runnable target, String name,
  10.                       long stackSize) {
  11.                 ....
  12.                 //通过构造函数传进来的Runnable对象直接赋值给了成员target。。。
  13.                 this.target = target;
  14.                 ....
  15.         }
  16.         public void run() {
  17.                 if (target != null) {
  18.                         /[color=Red]/最重要的一点,居然调用的是成员变量中的run方法![/color]
  19.                         target.run();
  20.                 }
  21.         }
  22. }
复制代码
一目了然了吧~事实上,Thread类中本身有有一个Runnable成员对象,run方法中的代码也就是调用Runnable对象的run,当我们在做new Thread(R)时,已经将Thread类中的Runnable对象指向了R,即四个窗口中的Runnable对象都指向了同一个对象R!

当JVM调用这四个窗口的run方法时,就是同时调用了四次R.run()来操作R.count!那么就实现了四窗口同时卖票了!

你的问题,我想我应该已经解释清楚了。然后再说一个事儿,继承Thread类的方式真的只能通过static count来操作同一个count吗??

第二种方式告诉我们,可以通过往Thread类中传递同一个操作对象(R)就能达到,那么我们能不能用某种方式在第一种情况下也实现呢?
  1. class Tickets{
  2.         private int count;
  3.         
  4.         public void Sell(){
  5.                 System.out.println(count.--);
  6.         }
  7. }

  8. class ChildThread{
  9.         private Tickets ticket;
  10.         ChildThread(Tickets ticket){
  11.                 this.ticket=ticket;
  12.         }
  13.         run(){
  14.                 ticket.Sell();
  15.         };
  16. }

  17. public class Test{
  18.         public static void main(String[] args){
  19.                 Tickets t = new Tickets();
  20.                 new ChildThread(t).start();
  21.                 new ChildThread(t).start();
  22.                 new ChildThread(t).start();
  23.                 new ChildThread(t).start();
  24.         }
  25. }
复制代码
你看,这样是不是在单继承的情况也实现了四窗口卖同一组票??哈哈,关键还是大家操作的都是一组票就成啦~~~(这种方式不实战推荐,仅用作比对学习~~^_^~

希望能对你有帮助!(斑斑求多给点儿分呗~~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2