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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

下面是书里面的源代码 我试着把main方法里的run()方法 改成了start()方法 发现程序也可以运行 但不是按照顺序进行打印剩下的票数的 请问一下 这到底是为什么? 在以后的写代码过程当中我该如何去选择使用run()方法还是start()方法

class MyThread implements Runnable{ // 继承Thread类,作为线程的实现类
private int ticket = 5 ;  // 表示一共有5张票
public void run(){ // 覆写run()方法,作为线程 的操作主体
  for(int i=0;i<100;i++){
   if(this.ticket>0){
    System.out.println("卖票:ticket = " + ticket--) ;
   }
  }
}
};
public class RunnableDemo02{
public static void main(String args[]){
  MyThread mt = new MyThread() ;  // 实例化对象
  new Thread(mt).run() ; // 调用线程主体
  new Thread(mt).run() ; // 调用线程主体
  new Thread(mt).run() ; // 调用线程主体
}
};

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
run()只是普通的调用方法
strat()是开启线程
回复 使用道具 举报
你是用实现的方式创建线程
流程如下:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
    自定义的run方法所属的的对象是Runnable接口的子类对象。
    要让线程去指定对象的run方法。就必须明确该run方法所属的对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

你前面几步都完成了,但最后你调运了run方法而不是start方法,所以你并没有启动线程.调运start方法才是开启线程.

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
楼主线程那应该还没仔细看
创建线程有两个方法:第一个继承Thread类,并复写其中的run()方法。
第二个是实现Runable接口,复写其中run()方法,并创建Thread类对象,然后将实现Runable的子类作为实参传递给Thread对象。
显然程序中用的是第二种方式。
楼主所说run()方法 改成了start()方法 发现程序也可以运行 但不是按照顺序进行打印剩下的票数的
因为线程是由start()方法开启的,这个方法的作用是开启线程,启动run()方法。而单独调用run()仅仅是对象调用,并没有开启线程
多线程并发执行,提高了程序运行效率,但结果是随机的,哪个线程抢到资源就执行哪个,也就是不会按照顺序打印票数了。
回复 使用道具 举报
class MyThread implements Runnable{ // 继承Thread类,作为线程的实现类
private int ticket = 100;  // 五张票难以说明问题,我在这里将票改为了100
public void run(){ // 覆写run()方法,作为线程 的操作主体
  for(int i=0;i<100;i++){
   if(this.ticket>0){
    System.out.println(Thread.currentThread().getName()+"卖票:ticket = " + ticket--) ; //输出语句中加入了线程的名称,以助于区分
   }
  }
}
};
public class  RunnableDemo02{
public static void main(String args[]){
  MyThread mt = new MyThread() ;  // 实例化对象
  new Thread(mt).start() ; // 调用start方法启动线程
  new Thread(mt).start() ; // 调用start方法启动线程
  new Thread(mt).start() ; //调用start方法启动线程
}
};
如实调用run()方法,主线程并没有将其他几个线程开启,而是自己将run()方法中的内容读完了,
而调用start()方法启动了该线程让该线程执行run()方法中的内容,以上红色部分是我做的一点修改
上传2张图以说明问题,第一张为你的源代码输出结果,第二张为我修改过的代码的输出结果。

未命名.jpg (23.55 KB, 下载次数: 24)

未命名.jpg

thread.png (8.58 KB, 下载次数: 25)

thread.png

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
你调用run方法时只是一个普通的调用函数的操作,那么换做Start方法时,这个new  Thread()对象会自动的调用你的主函数里面实现接口的run方法,就好比一辆遥控的小轿车,我可以通过远程遥控器来开启,也可以进到车子里面用钥匙去开启,结果都一样的!
回复 使用道具 举报
谢谢各位大侠相助,现在明白了.谢谢!!!
回复 使用道具 举报
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:

通过调用Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,
Run方法运行结束,
此线程终止,
而CPU再运行其它线程,



2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:

而如果直接用Run方法,
这只是调用一个方法而已,
程序中依然只有主线程--这一个线程,
其程序执行路径还是只有一条,
这样就没有达到写线程的目的。

评分

参与人数 1技术分 +3 收起 理由
张_涛 + 3 由于名字没改过来,错过的技术分补偿!.

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马