Java线程启动先后顺序问题

时间:2021-04-12 20:22:05

public class Test2 implements Runnable{
int b = 100;

public synchronized void m1() throws InterruptedException {
System.out.println("m1 is start");
b = 1000;
//Thread.sleep(5000);
System.out.println("m1.b="+b);
}

public synchronized void m2() throws InterruptedException { //去除synchronized后就是输出2000
System.out.println("m2 is start");
Thread.sleep(2000);
b=2000;
System.out.println("m2 is over");
}

public void run(){
try {
m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws InterruptedException {
Test2 tt = new Test2();
Thread t = new Thread(tt);
t.start();

tt.m2();
System.out.println("main.b="+tt.b);
}
}


为什么tt.m2()一定会优先于run()方法调用的m1()方法呢?求大神

24 个解决方案

#1


不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

#2


引用 1 楼 abcdefghiijklmnopqrs的回复:
不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

谢谢,是确定了m2先执行,还是很感谢你用心的回答!

#3


引用 1 楼 abcdefghiijklmnopqrs的回复:
不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

刚刚问了下老师,应该是你后面说的那个问题

#4


main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

#5


该回复于2015-12-23 11:18:31被管理员删除

#6


只是因为main线程先于Test2抢到了执行权

#7


引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了

#8


该回复于2015-12-23 16:27:18被管理员删除

#9


引用 7 楼 ziwang_ 的回复:
Quote: 引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了
优先级高不一定先执行

#10


引用 9 楼 abcdefghiijklmnopqrs的回复:
Quote: 引用 7 楼 ziwang_ 的回复:

Quote: 引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了
优先级高不一定先执行

也是哦,我之前是想的最开始的一瞬间是主函数的先进行

#11


Thread.yield() 
理解了这个方法,你就理解你现在问的这个问题了。

#12


调用start之后,线程只是处于等待调度的“就绪”状态,并没有启动。调试多线程最好用日志,调试器要么只暂停一个线程,要么全部挂起,容易让人困扰的。

#13


Java线程启动先后顺序问题

#14


"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴

#15


只是因为main线程先于Test2抢到了执行权

#16


不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了
刚刚问了下老师,应该是你后面说的那个问题

#17


我觉得可以这样理解,不知道对不对,在程序运行时,主线程已经启动并在运行中,而你另外起一个线程start表示线程处于就绪状态,还要等JVM机制调用进入运行状态,所以一般来讲这种简单的程序主线程执行的要快一些

#18


main方法是一个线程 
然后你
Test2 tt = new Test2();
        Thread t = new Thread(tt);
        t.start();
         
        tt.m2();
这代码的意思是 
t.start新起一个线程去运行run方法
但是对main这个线程来说
他会继续往下走 执行tt.m2
一个是新起线程去执行
一个是在本线程执行
当然是m2快
至于调试的时候因为你把main的线程给挂起来了
而影响不到新起来的run线程
所以run先跑

#19


引用 14 楼 ziwang_ 的回复:
"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴
赞!!!!

#20


java线程,正在学习,谢谢分享。

#21


learning~

#22


你在另外一个类里面测试一下

#23


引用 14 楼 ziwang_ 的回复:
"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴


这个解释真的很赞。建议楼主尝试试用一下yield:

    public static void main(String[] args) throws InterruptedException {
        Test2 tt = new Test2();
        Thread t = new Thread(tt);
        t.start();
        Thread.yield();
        tt.m2();
        System.out.println("main.b="+tt.b);
    }
这样出来的结果就未必总是tt.m2()先执行了。

#24


感谢大神们的分享

#1


不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

#2


引用 1 楼 abcdefghiijklmnopqrs的回复:
不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

谢谢,是确定了m2先执行,还是很感谢你用心的回答!

#3


引用 1 楼 abcdefghiijklmnopqrs的回复:
不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了

刚刚问了下老师,应该是你后面说的那个问题

#4


main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

#5


该回复于2015-12-23 11:18:31被管理员删除

#6


只是因为main线程先于Test2抢到了执行权

#7


引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了

#8


该回复于2015-12-23 16:27:18被管理员删除

#9


引用 7 楼 ziwang_ 的回复:
Quote: 引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了
优先级高不一定先执行

#10


引用 9 楼 abcdefghiijklmnopqrs的回复:
Quote: 引用 7 楼 ziwang_ 的回复:

Quote: 引用 4 楼 Cx_轩的回复:
main方法 代表的是主线程的 他的优先度好像要高一点 Java线程启动先后顺序问题  如果你在里面创建多个线程 他们则是同级的

我之前也是这么想的,我老师后来用debug调试,成了m1先执行了
优先级高不一定先执行

也是哦,我之前是想的最开始的一瞬间是主函数的先进行

#11


Thread.yield() 
理解了这个方法,你就理解你现在问的这个问题了。

#12


调用start之后,线程只是处于等待调度的“就绪”状态,并没有启动。调试多线程最好用日志,调试器要么只暂停一个线程,要么全部挂起,容易让人困扰的。

#13


Java线程启动先后顺序问题

#14


"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴

#15


只是因为main线程先于Test2抢到了执行权

#16


不一定,先多测试试试
如果一直是tt.m2()一定会优先于run()方法调用的m1()方法,那可能是java线程调度器的影响具体就不知道了
刚刚问了下老师,应该是你后面说的那个问题

#17


我觉得可以这样理解,不知道对不对,在程序运行时,主线程已经启动并在运行中,而你另外起一个线程start表示线程处于就绪状态,还要等JVM机制调用进入运行状态,所以一般来讲这种简单的程序主线程执行的要快一些

#18


main方法是一个线程 
然后你
Test2 tt = new Test2();
        Thread t = new Thread(tt);
        t.start();
         
        tt.m2();
这代码的意思是 
t.start新起一个线程去运行run方法
但是对main这个线程来说
他会继续往下走 执行tt.m2
一个是新起线程去执行
一个是在本线程执行
当然是m2快
至于调试的时候因为你把main的线程给挂起来了
而影响不到新起来的run线程
所以run先跑

#19


引用 14 楼 ziwang_ 的回复:
"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴
赞!!!!

#20


java线程,正在学习,谢谢分享。

#21


learning~

#22


你在另外一个类里面测试一下

#23


引用 14 楼 ziwang_ 的回复:
"在HotSpot VM上,按照链接里的代码的写法,其实tt.m2()几乎总是会比Test2.run()要更早被调用,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到您指定的入口方法(这里就是Thread.run() -&gt; Runnable.run() -&gt; Test2.run())。<br>这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖,也不要因为规范没要求而拒绝承认实现中有这样的特征。"谢谢,结贴


这个解释真的很赞。建议楼主尝试试用一下yield:

    public static void main(String[] args) throws InterruptedException {
        Test2 tt = new Test2();
        Thread t = new Thread(tt);
        t.start();
        Thread.yield();
        tt.m2();
        System.out.println("main.b="+tt.b);
    }
这样出来的结果就未必总是tt.m2()先执行了。

#24


感谢大神们的分享