A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李文帅 中级黑马   /  2013-10-26 16:54  /  1295 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李文帅 于 2013-10-26 19:52 编辑

今天看了毕老师讲的第二种创建线程方法的视频,对下面的售票例子不是很理解
  1. public class Ticket implements Runnable{
  2.         private int ticket = 100;
  3.         public void run(){
  4.                 while(true){
  5.                         if(ticket>0){
  6.                         System.out.println(Thread.currentThread().getName()+" sale..."+ticket--);
  7.                         }
  8.                 }
  9.         }

  10. }
  11. public class TicketDemo {

  12.         /**
  13.          * @param args
  14.          */
  15.         public static void main(String[] args) {
  16.                 // TODO Auto-generated method stub
  17.                 Ticket t = new Ticket();
  18.                
  19.                 //创建线程
  20.                 Thread t1 = new Thread(t);
  21.                 Thread t2 = new Thread(t);
  22.                 Thread t3 = new Thread(t);
  23.                 Thread t4 = new Thread(t);
  24.                
  25.                 //开启线程
  26.                 t1.start();
  27.                 t2.start();
  28.                 t3.start();
  29.                 t4.start();
  30.         }

  31. }
复制代码
程序为什么会运行Ticket子类中的run()方法,而不是运行Thread类中的run()方法呢

评分

参与人数 1技术分 +1 收起 理由
To + 1 神马都是浮云

查看全部评分

8 个回复

倒序浏览
这个问题很好,你接着看完后面的视频就会明白了。
这里要看Thread的源代码了:

Thread的run方法的实现

1 public void run() {
2     if (target != null) {
3         target.run();
4     }
5 }

这里的tagert就是传入的Runable的实现子类。
注意:1,使用继承Thread创建线程类时,需要重写run方法,因为默认的run方法什么也不干。
2,当我们使用Runnable接口实现线程类时,为了启动线程,需要先把该线程类实例初始化一个Thread,实际上就执行了如下构造函数:

1 public Thread(Runnable target) {
2     init(null, target, "Thread-" + nextThreadNum(), 0);
3 }
(init为内部初始化方法,不用理解。)
  所以即是把线程类的引用保存到target中。这样,当调用Thread的run方法时,target就不为空了,而是继续调用了target的run方法,所以我们需要实现Runnable的run方法。这样通过Thread的run方法就调用到了Runnable实现类中的run方法。

  这也是Runnable接口实现的线程类需要这样启动的原因。

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 赞一个!

查看全部评分

回复 使用道具 举报
Stephen_Chow 发表于 2013-10-26 17:22
这个问题很好,你接着看完后面的视频就会明白了。
这里要看Thread的源代码了:

领情参考这篇博文
地址:http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html

http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html
回复 使用道具 举报
Stephen_Chow 发表于 2013-10-26 17:34
领情参考这篇博文
地址:http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html

谢谢你的解答,虽然还是有点模糊,但还是要谢谢你,继续看视频的,应该能完全理解:)
回复 使用道具 举报
你的Ticket类是实现了Runnable接口,需要对Runnable中的run()方法进行重写。
你先创建了Ticket对象,再把这个对象当做参数传入了Thread对象,
所以执行的是你覆写的run()方法。
回复 使用道具 举报
看来哥么你对多线程的理解很浅
线程的建立有两种方式:
1.继承Thread类,重写run() 方法
2.时限Runnable接口,覆盖Runnable接口中的run()方法

Runnable是一个接口,不能创建对象,你的Ticket类重写了属于它特有的行为的run()方法,当然是运行Ticket类的run方法

好好学习,把每个知识点都学透,不懂可以问我

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
亲爱哒楼主,看看Thread方法的源码






在看看你调用的构造函数



然后我在init里面找到了这个东西




所以,你执行的也就是你传入的runable接口的run方法







回复 使用道具 举报
麦子 发表于 2013-10-26 19:06
看来哥么你对多线程的理解很浅
线程的建立有两种方式:
1.继承Thread类,重写run() 方法

我刚看到线程这里,所以还不是很理解,谢谢你的解答,如果有不会的问题还希望你能多多指导:)
回复 使用道具 举报
黄小贝 发表于 2013-10-26 19:10
亲爱哒楼主,看看Thread方法的源码

谢谢你的解答,也让我知道了查看源码也是很有用的:)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马