黑马程序员技术交流社区
标题: 大家帮我看看代码,关于线程问题 [打印本页]
作者: job 时间: 2014-4-11 22:55
标题: 大家帮我看看代码,关于线程问题
本帖最后由 job 于 2014-4-12 21:34 编辑
我的理解是t.start()开启一个线程后先执行show1(),但show()刚执行就睡了100毫秒。接下来主线程执行show2(),虽然show2()也睡了但只有20毫秒,所以输出应该是:show2----a=2 show1----a=2 因为show2最后给a赋值2。但实际结果是
难道有系统默认锁。
作者: 向日葵的曙光 时间: 2014-4-12 08:37
你首先要理解什么是线程,线程的执行的代码必须放在run方法中,show2明显没有放在run方法中
你这实现的是一个接口,所以如果想开启两个线程就必须创建两个Thread类,然后再调用start开启线程
好好看书啊
作者: 李程 时间: 2014-4-12 13:21
结果都已经告诉你答案了吧。。。当a被赋值为1的时候,这个线程进行休眠,估计就将这个对象的私有数据锁住了,不能再赋值了,否则就应该是你说的哪个结果!!程序说明一切吧,已经有结果了
作者: ò壞尛孩 时间: 2014-4-12 15:14
主函数执行过程中,其实只有2个线程在运行,一个是main一个是t,
t被start后,执行t里面的run()方法,但是还没有执行过程中main抢到了
资源,执行后面的show2(),然后t才执行run方法里面的show();
这里其实sleep 20ms 2000ms对于cpu来说是非常短暂的!也许你睡20ms,但是cpu在执行其他的,这20ms和睡2000ms没区别,尤其现在的计算机都是双核以上了!
作者: miedongdong 时间: 2014-4-12 18:45
本帖最后由 miedongdong 于 2014-4-12 18:52 编辑
看到这个问题,我也不是很懂,真惨!下午自己动手试了一下,感觉有点懂了,
我根据你的程序来说一下我的想法,如果有不对的请指正:
主线程和自定义线程在运行的时候都会抢夺cpu执行权,这里就会牵涉到输出结果的问题,两个方法里面都有sleep方法,只要其中一个线程执行了sleep方法,那么另一个线程就会启动。在你的编译结果中,就是主线程执行show2(),此时把2赋值给栈中的 a (此时还没输出a),先执行sleep(),此时自定义线程就会拿到执行权,show1()就把栈中的a修改成1,当睡眠100毫秒期间,show2中的打印语句执行,可是此时栈中只有a=1,所以打印出来1,show1中打印的1也是如此。
执行流程如下:main-->show2()-->a=2-->sleep(20)-->show1()-->a=1-->sleep(100)-->show2{sop(1)}-->show1{sop(1)};
我根据你的程序做了如下修改:
- import java.util.*;
- class ThreadDemo implements Runnable
- {
- public int a ;
- public void show1()throws Exception
- {
- a = 1;
- Thread.sleep(100);
- System.out.println("show1....."+a);
- }
-
- public void show2()throws Exception
- {
- System.out.println("show......"+a);//只是增加这行代码
- a = 2;
- Thread.sleep(20);
- System.out.println("show2....."+a);
- }
- public void run()
- {
- try
- {
- show1();
- }
- catch (Exception e)
- {
- }
-
- }
-
- }
- class client
- {
- public static void main(String[] args) throws Exception
- {
- ThreadDemo td = new ThreadDemo();
- Thread t = new Thread(td);
- t.start();
- td.show2();
- }
- }
- 打印结果如下:(我比较幸运,一下子就能出现两个不同的效果)
- E:\Study\1-today\1-javados\0410>javac ThreadDemo.java
- E:\Study\1-today\1-javados\0410>java client
- show......0
- show2.....2
- show1.....2
- E:\Study\1-today\1-javados\0410>java client
- show......1
- show2.....2
- show1.....2
复制代码
跟你的程序只是修改了一行,怎么会有这两个效果?
1、说明一下两个打印结果中的第一行不同结果的原因:之前说过主线程和自定义线程会抢夺执行权,那么第一个打印结果就是主线程先执行show2方法,一开始a是默认为0,所以第一个打印方法打印的是0,那么第二个打印结果为啥会是1呢?那就是自定义线程先执行show1(),此时刚把1赋值给a后,就立刻给主线程抢去了执行权,此时栈中的a的值为1,所以打印1。
2、至于为啥两个结果的最后两个都是打印2,我暂时还没找到依据,只是有一个猜测,希望哪位同学能帮忙解析一下,在此谢谢了。我的猜测是:主线程操作的方法是后面,按照执行顺序来看的话,就是自定义线程先睡眠,所以主线程中的a=2会覆盖之前的值,打印结果就是2。
但是我也有产生了疑问,希望有同学能帮忙解答一下:
1、为什么在修改后的程序中,sleep()之前主线程都会抢夺执行权,而不会提前sleep呢?而楼主的线程就是主线程先执行sleep()呢
2、在只有主线程和一个自定义线程时,是不是主线程优先级高一点,会执行多一点呢?
感谢你提出的问题,我今天也复习了一下多线程,基础还是不好啊,一起学习,一起进步!!
作者: job 时间: 2014-4-12 20:50
这里我主要是想知道主线程和自己创建的线程之间的关系,所以才没把show2放到run中,而是由main主线程来调用它。
作者: job 时间: 2014-4-12 20:59
综合你的理解以及楼下的思路,应该会出现同时两个1和两个2的情况,所以我改了下程序在两个show的第一行分别加上了这个:System.out.println("showa----a=" + a);和System.out.println("showb----a=" + a);结果就出现双1双2的情况,但是加的这两行总是0,不知道为什么。
作者: job 时间: 2014-4-12 21:13
我才你你应该是红领巾吧!热心助人!:P十分感谢你看了问题并作出了如此详尽的回答。我根据你的思路,在show1也加了这个System.out.println("showa----a=" + a);出现了双1双2的情况,双1你已经解释过了,双2应该就是main-->show1()-->a=1-->sleep(100)-->show2-->a=2-->show2{sop(2)}-->show1{sop(2)};
作者: ò壞尛孩 时间: 2014-4-12 21:47
你在show()1和2中第一句加show,一个show属于run方法,一个由主线程的类对象调用。LZ你的sleep()是想看看是main还是自定义的线程先执行的问题吗?
其实双1双2都会出现,因为在两个线程的操作中都是多语句,只是两个出现的概率不同而已,我看了下楼下的代码
- import java.util.*;
- class ThreadDemo implements Runnable
- {
- public int a ;
- public void show1()throws Exception
- {
- a = 1;
- Thread.sleep(100);
- System.out.println("show1....."+a);
- }
-
- public void show2()throws Exception
- {
- System.out.println("show......"+a);//只是增加这行代码
- a = 2;
- Thread.sleep(20);
- System.out.println("show2....."+a);
- }
- public void run()
- {
- try
- {
- show1();
- }
- catch (Exception e)
- {
- }
-
- }
-
- }
- class Test
- {
- public static void main(String[] args) throws Exception
- {
- ThreadDemo td = new ThreadDemo();
- Thread t = new Thread(td);
- t.start();
- td.show2();
- }
- }
复制代码
我运行得到了三个结果
show......0
show2.....2
show1.....2
show......1
show2.....2
show1.....2
show......0
show2.....1
show1.....1
双2出现的最多 双1的概率很小!但是第一个收为什么会是1或者0,楼下的解释很有道理我就不说了,主线程先执行show2的第一句,打印出0,执行到a=2之后被自定义线程抢夺执行权,执行show1(),a=1,然后打印1,主线程再执行下面的打印也是1 就是结果 011
0 2 2 就是 主线程- >执行打印>自定义线程执行a=1>主线程执行完a=2>自定义线程执行
1 2 2 就是 自定义线程执行show1 a=1>主线程抢打印 >主线程执行完 >自定义线程执行
其实这样分析我觉得 很没必要,因为线程中执行的是多条语句,当多个线程执行时,就必然会出现这样的问题,
其实真正的结果应该还有 0 1 2 ; 0 2 1 ; 1 1 2; 这三种,只是因为sleep睡眠的时间间隔问题,所以出现的概率极低!
如果没有sleep语句。这6种组合都会出现,
结果中show2先打印show1后打印的原因是主线程睡20ms,自定义线程睡100ms,而a=1 a=2是在睡眠语句前面 所以你不管怎么执行
都会是双1 双2 ,是因为sleep的问题。
楼下说是不是主线程比自定义线程 抢夺资源的能力强些 ,我觉得完全不可能!后面的教学视频有说线程默认优先级都是5,抢夺资源能力是默认的!
只是sleep长短的问题!
作者: ò壞尛孩 时间: 2014-4-12 22:04
双1的结果也有,不过很少。双1双2 的原因是 a=1 a=2是在睡眠之前, 但是为啥主线程都会先执行,是因为自定义线程里面睡眠100ms ,即使先执行自定义线程,主线程还是会被执行!只是结果貌似看是主线程先执行的,其实自定义线程也有可能先执行只是被睡在那了!不知道我解答的对不对!
作者: miedongdong 时间: 2014-4-12 22:23
呵呵,你怎么能得到011的结果,厉害!可能我们电脑的核数不同吧,我就弄不出来了,虽然我也有考虑过这个结果,不过就是得不到。对于你说的还有3个结果,在这个情况下我是不认同的,只有两个线程,那么一个线程sleep后,另一个就会执行,a的值就会被覆盖掉,不过3个以上就有可能了:lol。
谢谢你提醒哈,我都忘记那个优先级都是默认是5的,我刚刚试了把sleep的时间都设置成一样,从该程序得到的结果还是双2结束,还是搞不懂呢~~
对于多线程真的得深入才能做得好,我给show1开始加上一句打印语句,去掉show2中的第一个打印语句,得到的结果就是211了,还是挺奇怪的。
作者: ò壞尛孩 时间: 2014-4-12 22:41
本帖最后由 ò壞尛孩 于 2014-4-12 22:42 编辑
011 可以得到 你多运行几下!我是双核CPU 09年买的联想笔记本!截图给你看,双1就是主线程show2未被唤醒前自定义线程就执行完就会出现双1.因为show1被睡100ms所以出现概率低。
后面的三种结果 我说的是在没有sleep可以得到!多条语句被多线程执行,什么样的结果都有可能,只是概率问题。
我觉得考虑这个没有意义,多线程一般都写锁的!不可能让多条语句出现在多线程中同时执行,肯定会出错!
作者: miedongdong 时间: 2014-4-12 22:46
恩恩,纠结这个是没什么意义,只不过可以让我们了解一下多线程。ps:我的电脑3核的
作者: ò壞尛孩 时间: 2014-4-12 22:55
:'(我才开始用论坛,看看我的技术分!啥时候才能报名啊!你应该已经加入黑马了吧!求指导啊!我还在走流程!
作者: 杨庆雷 时间: 2014-4-13 00:14
package ArrayList;
import java.util.*;
class ThreadDemo implements Runnable
{
public int a ;
public void show1()throws Exception
{
a = 1; // 1 所有的组合为 ①:1→4→5→2→6→7→3
Thread.sleep(100); // 2 ②:1→4→2→5→6→7→3
System.out.println("show1....."+a); // 3 ③:1→4→5→6→2→7→3
④:4→5→6→1→2→7→3
⑤:4→5→1→6→2→7→3
} ⑥:4→5→1→2→6→7→3
输出结果。。。。。。。 麻烦啊
public void show2()throws Exception
{
System.out.println("show......"+a); // 4
a = 2; // 5
Thread.sleep(20); // 6
System.out.println("show2....."+a); // 7
}
public void run()
{
try
{
show1();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
ThreadDemo td = new ThreadDemo();
Thread t = new Thread(td);
t.start();
td.show2();
}
}
组合都是debug到的
其实这就是两个线程 一个主线程 一个新建的线程 碰到sleep当前线程停止 必执行另一个线程
有一个地方比较特殊 如果由2→6 会继续当前线程 执行7 因为 6 sleep的时间短 只有20毫秒
作者: miedongdong 时间: 2014-4-13 07:40
:handshake:handshake 还没有啊,我也是在走流程中,一起加油吧
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |