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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© job 中级黑马   /  2014-4-11 22:55  /  2871 人查看  /  15 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 job 于 2014-4-12 21:34 编辑


我的理解是t.start()开启一个线程后先执行show1(),但show()刚执行就睡了100毫秒。接下来主线程执行show2(),虽然show2()也睡了但只有20毫秒,所以输出应该是:show2----a=2         show1----a=2       因为show2最后给a赋值2。但实际结果是 难道有系统默认锁。

评分

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

查看全部评分

15 个回复

倒序浏览
你首先要理解什么是线程,线程的执行的代码必须放在run方法中,show2明显没有放在run方法中
你这实现的是一个接口,所以如果想开启两个线程就必须创建两个Thread类,然后再调用start开启线程
好好看书啊
回复 使用道具 举报
结果都已经告诉你答案了吧。。。当a被赋值为1的时候,这个线程进行休眠,估计就将这个对象的私有数据锁住了,不能再赋值了,否则就应该是你说的哪个结果!!程序说明一切吧,已经有结果了
回复 使用道具 举报

主函数执行过程中,其实只有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:52 编辑

看到这个问题,我也不是很懂,真惨!下午自己动手试了一下,感觉有点懂了,
我根据你的程序来说一下我的想法,如果有不对的请指正:
主线程和自定义线程在运行的时候都会抢夺cpu执行权,这里就会牵涉到输出结果的问题,两个方法里面都有sleep方法,只要其中一个线程执行了sleep方法,那么另一个线程就会启动。在你的编译结果中,就是主线程执行show2(),此时把2赋值给栈中的 a (此时还没输出a,先执行sleep(),此时自定义线程就会拿到执行权,show1()就把栈中的a修改成1,当睡眠100毫秒期间,show2中的打印语句执行,可是此时栈中只有a=1,所以打印出来1show1中打印的1也是如此。

执行流程如下:main-->show2()-->a=2-->sleep(20)-->show1()-->a=1-->sleep(100)-->show2{sop(1)}-->show1{sop(1)};

我根据你的程序做了如下修改:


  1. import java.util.*;

  2. class ThreadDemo implements Runnable
  3. {
  4.         public int a ;

  5.         public  void show1()throws Exception
  6.         {
  7.                 a = 1;
  8.                 Thread.sleep(100);
  9.                 System.out.println("show1....."+a);

  10.         }
  11.         
  12.         public  void show2()throws Exception
  13.         {
  14.                 System.out.println("show......"+a);//只是增加这行代码
  15.                 a = 2;
  16.                 Thread.sleep(20);
  17.                 System.out.println("show2....."+a);
  18.         }

  19.         public void run()
  20.         {
  21.                 try
  22.                 {
  23.                         show1();
  24.                 }
  25.                 catch (Exception e)
  26.                 {
  27.                 }
  28.                
  29.         }

  30.         
  31. }

  32. class client
  33. {
  34.         public static void main(String[] args) throws Exception
  35.         {
  36.                 ThreadDemo td = new ThreadDemo();
  37.                 Thread t = new Thread(td);
  38.                 t.start();
  39.                 td.show2();
  40.         }
  41. }

  42. 打印结果如下:(我比较幸运,一下子就能出现两个不同的效果)
  43. E:\Study\1-today\1-javados\0410>javac ThreadDemo.java

  44. E:\Study\1-today\1-javados\0410>java client
  45. show......0
  46. show2.....2
  47. show1.....2

  48. E:\Study\1-today\1-javados\0410>java client
  49. show......1
  50. show2.....2
  51. show1.....2
复制代码




跟你的程序只是修改了一行,怎么会有这两个效果?
1、说明一下两个打印结果中的第一行不同结果的原因:之前说过主线程和自定义线程会抢夺执行权,那么第一个打印结果就是主线程先执行show2方法,一开始a是默认为0,所以第一个打印方法打印的是0,那么第二个打印结果为啥会是1呢?那就是自定义线程先执行show1(),此时刚把1赋值给a后,就立刻给主线程抢去了执行权,此时栈中的a的值为1,所以打印1
2、至于为啥两个结果的最后两个都是打印2,我暂时还没找到依据,只是有一个猜测,希望哪位同学能帮忙解析一下,在此谢谢了。我的猜测是:主线程操作的方法是后面,按照执行顺序来看的话,就是自定义线程先睡眠,所以主线程中的a=2会覆盖之前的值,打印结果就是2


但是我也有产生了疑问,希望有同学能帮忙解答一下:
1、为什么在修改后的程序中,sleep()之前主线程都会抢夺执行权,而不会提前sleep呢?而楼主的线程就是主线程先执行sleep()呢
2、在只有主线程和一个自定义线程时,是不是主线程优先级高一点,会执行多一点呢?


感谢你提出的问题,我今天也复习了一下多线程,基础还是不好啊,一起学习,一起进步!!

评分

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

查看全部评分

回复 使用道具 举报
向日葵的曙光 发表于 2014-4-12 08:37
你首先要理解什么是线程,线程的执行的代码必须放在run方法中,show2明显没有放在run方法中
你这实现的是一 ...

这里我主要是想知道主线程和自己创建的线程之间的关系,所以才没把show2放到run中,而是由main主线程来调用它。
回复 使用道具 举报
job 中级黑马 2014-4-12 20:59:40
7#
ò壞尛孩 发表于 2014-4-12 15:14
主函数执行过程中,其实只有2个线程在运行,一个是main一个是t,
t被start后,执行t里面的run()方法,但是还 ...

综合你的理解以及楼下的思路,应该会出现同时两个1和两个2的情况,所以我改了下程序在两个show的第一行分别加上了这个:System.out.println("showa----a=" + a);和System.out.println("showb----a=" + a);结果就出现双1双2的情况,但是加的这两行总是0,不知道为什么。
回复 使用道具 举报
job 中级黑马 2014-4-12 21:13:19
8#
miedongdong 发表于 2014-4-12 18:45
看到这个问题,我也不是很懂,真惨!下午自己动手试了一下,感觉有点懂了,我根据你的程序来说一下我的想法 ...

我才你你应该是红领巾吧!热心助人!: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)};
回复 使用道具 举报
job 发表于 2014-4-12 20:59
综合你的理解以及楼下的思路,应该会出现同时两个1和两个2的情况,所以我改了下程序在两个show的第一行分 ...

你在show()1和2中第一句加show,一个show属于run方法,一个由主线程的类对象调用。LZ你的sleep()是想看看是main还是自定义的线程先执行的问题吗?
其实双1双2都会出现,因为在两个线程的操作中都是多语句,只是两个出现的概率不同而已,我看了下楼下的代码

  1. import java.util.*;

  2. class ThreadDemo implements Runnable
  3. {
  4.         public int a ;

  5.         public  void show1()throws Exception
  6.         {
  7.                 a = 1;
  8.                 Thread.sleep(100);
  9.                 System.out.println("show1....."+a);

  10.         }
  11.         
  12.         public  void show2()throws Exception
  13.         {
  14.                 System.out.println("show......"+a);//只是增加这行代码
  15.                 a = 2;
  16.                 Thread.sleep(20);
  17.                 System.out.println("show2....."+a);
  18.         }

  19.         public void run()
  20.         {
  21.                 try
  22.                 {
  23.                         show1();
  24.                 }
  25.                 catch (Exception e)
  26.                 {
  27.                 }
  28.                
  29.         }

  30.         
  31. }

  32. class Test
  33. {
  34.         public static void main(String[] args) throws Exception
  35.         {
  36.                 ThreadDemo td = new ThreadDemo();
  37.                 Thread t = new Thread(td);
  38.                 t.start();
  39.                 td.show2();
  40.         }
  41. }
复制代码

我运行得到了三个结果
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长短的问题!

评分

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

查看全部评分

回复 使用道具 举报
miedongdong 发表于 2014-4-12 18:45
看到这个问题,我也不是很懂,真惨!下午自己动手试了一下,感觉有点懂了,我根据你的程序来说一下我的想法 ...

双1的结果也有,不过很少。双1双2 的原因是 a=1 a=2是在睡眠之前, 但是为啥主线程都会先执行,是因为自定义线程里面睡眠100ms ,即使先执行自定义线程,主线程还是会被执行!只是结果貌似看是主线程先执行的,其实自定义线程也有可能先执行只是被睡在那了!不知道我解答的对不对!
回复 使用道具 举报
ò壞尛孩 发表于 2014-4-12 21:47
你在show()1和2中第一句加show,一个show属于run方法,一个由主线程的类对象调用。LZ你的sleep()是想看看 ...

呵呵,你怎么能得到011的结果,厉害!可能我们电脑的核数不同吧,我就弄不出来了,虽然我也有考虑过这个结果,不过就是得不到。对于你说的还有3个结果,在这个情况下我是不认同的,只有两个线程,那么一个线程sleep后,另一个就会执行,a的值就会被覆盖掉,不过3个以上就有可能了:lol。
谢谢你提醒哈,我都忘记那个优先级都是默认是5的,我刚刚试了把sleep的时间都设置成一样,从该程序得到的结果还是双2结束,还是搞不懂呢~~
对于多线程真的得深入才能做得好,我给show1开始加上一句打印语句,去掉show2中的第一个打印语句,得到的结果就是211了,还是挺奇怪的。
回复 使用道具 举报
本帖最后由 ò壞尛孩 于 2014-4-12 22:42 编辑
miedongdong 发表于 2014-4-12 22:23
呵呵,你怎么能得到011的结果,厉害!可能我们电脑的核数不同吧,我就弄不出来了,虽然我也有考虑过这个 ...

011 可以得到 你多运行几下!我是双核CPU  09年买的联想笔记本!截图给你看,双1就是主线程show2未被唤醒前自定义线程就执行完就会出现双1.因为show1被睡100ms所以出现概率低。
后面的三种结果  我说的是在没有sleep可以得到!多条语句被多线程执行,什么样的结果都有可能,只是概率问题。
我觉得考虑这个没有意义,多线程一般都写锁的!不可能让多条语句出现在多线程中同时执行,肯定会出错!



回复 使用道具 举报
ò壞尛孩 发表于 2014-4-12 22:41
011 可以得到 你多运行几下!我是双核CPU  09年买的联想笔记本!截图给你看,双1就是主线程show2未被唤醒前 ...

恩恩,纠结这个是没什么意义,只不过可以让我们了解一下多线程。ps:我的电脑3核的
回复 使用道具 举报
miedongdong 发表于 2014-4-12 22:46
恩恩,纠结这个是没什么意义,只不过可以让我们了解一下多线程。ps:我的电脑3核的 ...

:'(我才开始用论坛,看看我的技术分!啥时候才能报名啊!你应该已经加入黑马了吧!求指导啊!我还在走流程!
回复 使用道具 举报
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毫秒

回复 使用道具 举报
ò壞尛孩 发表于 2014-4-12 22:55
我才开始用论坛,看看我的技术分!啥时候才能报名啊!你应该已经加入黑马了吧!求指导啊!我还在走流 ...

:handshake:handshake 还没有啊,我也是在走流程中,一起加油吧
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马