黑马程序员技术交流社区

标题: 求解线程中start()和run()的问题 [打印本页]

作者: miedongdong    时间: 2013-10-28 15:37
标题: 求解线程中start()和run()的问题
本帖最后由 miedongdong 于 2013-10-29 22:18 编辑

class Demo01_StartThread {
public static void main(String[] args) {    // 默认启动一条线程(主线程)
  new MyThread().run();   //start();         // 启动一条新线程(做一件事情)// 我第一次在这行把start()改成run();
  new Thread(new MyRunnable()).start();   // 启动一条新线程(做一件事情)//我第二次在这行把start()改成run(),同时把第一次修改成run()处还原成start();
  
  // 主线程也要做一件事情
  for (int i = 0; i < 100; i++)
   System.out.println(Thread.currentThread().getName()+":中关村软件园: " + i);
}
}
class MyThread extends Thread {
public void run() {
  for (int i = 0; i < 100; i++)
   System.out.println(getName() + ": 黑马程序员: " + i);
}
}
class MyRunnable implements Runnable {
public void run() {
  for (int i = 0; i < 100; i++)
   System.out.println(Thread.currentThread().getName() + ": 传智播客: " + i);
}
}
这是黑马YY公开课的源码,由于没赶上,只能自己看一下。
我修改了两次修改上面的代码,第一次修改后,执行结果是:由main线程一次性把MyThread中的run()先完成,其他的再交替完成
而第二次修改成run(),执行结果是:main线程会跟第一个线程交替执行,而且主函数中自己的执行代码也是一次性完成,没有和其他线程交替完成。

请问为什么会造成这样的情况呢,主函数的线程运行原理是怎样的??


作者: Jim-剣◆﹏    时间: 2013-10-28 23:58
怎么就没人回复捏
我说说我的理解,看看有没有说中你的点
其实最重要的点就是,要开启多线程,必须是通过调用start(),主线程执行到对象调用start()方法,则会额外开辟一个线程
而如果通过调用run(),没有新开辟线程,则还是只存在main线程
这样就好理解了你把start()修改成run()为什么会由main线程一次性把MyThread中的run()先完成,其他的再交替完成
下面的也同样这样理解
作者: miedongdong    时间: 2013-10-29 00:47
Jim-剣◆﹏ 发表于 2013-10-28 23:58
怎么就没人回复捏
我说说我的理解,看看有没有说中你的点
其实最重要的点就是,要开启多线程,必须是通过调 ...

谢谢你的回复,可能是我领悟力不好吧,还是不大懂。
感觉现在论坛都没生气一样了,可能是论坛对老人的吸引力没那么足吧
作者: 黄炳期    时间: 2013-10-29 09:06
多线程这个知识点确实很难理解,特别是安全问题和死锁问题。
楼主也不必着急,公开课上老师讲的是重点难点,速度也比较快,没有深入剖析,
你可以看看毕向东老师的基础视频,里面讲的更详细!
作者: Stephen_Chow    时间: 2013-10-29 09:17
首先你要明确这两个方法的区别:
strart()方法,用于启动一个线程。(线程会处于就绪状态,执行的时候底层会调用run())。
而run()只是对象的一个普通的方法。(只不过是用来存放线程的运行代码而已,就这点特殊)

调用前者会启动一个线程,而后者只是普通的对象调用方法。所以这就明了了。
其他的再交替完成
第一次:当然先执行对象调用方法呗,即由main线程一次性把MyThread中的run()先完成,
然后是main线程和  new Thread(new MyRunnable()).start();  共两个线程交替抢夺CPU执行权,去运行。

第二次:与第一次同理,  new MyThread().start();和main两个线程,在调用对象的方法。
这里有一个重要的知识点:当一个Thread类接受一个Runnable接口的实现类时,在调用Thread类的run方法,他会先判断,不为空则调用接口实现类的。
Thread的源代码:  
构造函数:传递的Runnable 实现类
public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

接着调用init初始化方法:
private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
                 this.target = target;
                 。。。。。。。。。
}
然后判断:
public void run() {
        if (target != null) {
            target.run();
        }
    }

所以很明白的调用 MyRunnable的run方法;
总之记住原则:调用start方法才会开启线程,调用run只是对象调用方法
建议你吧毕老师java基础里的线程那一块,认真看一遍,就会有收获的,加油,一起进步
作者: miedongdong    时间: 2013-10-29 10:29
Stephen_Chow 发表于 2013-10-29 09:17
首先你要明确这两个方法的区别:
strart()方法,用于启动一个线程。(线程会处于就绪状态,执行的时候底层 ...

好的,再去听一下毕老师的课,暂时脑子还是转不过来
谢谢你的回复!加油
作者: 零下五度的水    时间: 2013-10-29 11:20
话说,你是用的MyEclipse吧
new MyThread().start() 有给说明的啊
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
说的是 start 方法调用 run 方法,结果是两条线程*同时*运行(他自己和另一条用run方法开启的线程)
意思大概是 start 会带动另一条线程一起跑,run 撑死就是被 start 带着跑,他自己没那本事拉着人跑
但是一条线程的 start 方法只能用一次,以后就只能用 run 了,感觉 start 就相当于大招,用一次就没了
作者: To    时间: 2013-10-29 21:42
楼主你好,如果问题已解决请将帖子状态修改为提问结束,
如果未解决请继续追问,谢谢合作
修改方法请看解释帖:http://bbs.itheima.com/thread-89313-1-1.html
作者: miedongdong    时间: 2013-10-29 22:16
零下五度的水 发表于 2013-10-29 11:20
话说,你是用的MyEclipse吧
new MyThread().start() 有给说明的啊
Causes this thread to begin execution; ...

我用命令行窗口运行的,看不到myeclipse中的解析。
你的解析很生动,谢谢了
作者: miedongdong    时间: 2013-10-29 22:18
仇邓强 发表于 2013-10-29 21:42
楼主你好,如果问题已解决请将帖子状态修改为提问结束,
如果未解决请继续追问,谢谢合作
修改方法请看解释 ...

还不是很理解,还是关了,要不以后都忘记关了




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