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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 沈子豪 中级黑马   /  2013-3-10 21:19  /  2065 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Demo extends Thread
{
        private String name;
        Demo(String name)
        {
         this.name=name;
        }
        public void run()
        {
         for(int x=0;x<300;x++)
        System.out.println(name);
        }
}
class ThreadDemo
{
        public static void main(String[] args)
        {
         Demo d1=new Demo("我");
         Demo d2=new Demo("你");
         d1.start();
         d2.start();
        }
}
这是双线程,但是为什么输出要么先是"我",要么先是"你",为什么不是交叉的?

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

10 个回复

正序浏览
本帖最后由 聂斌 于 2013-3-11 02:35 编辑

cpu切换是随机的

发现运行结果每一次都不同。
因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。
明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)
cpu在做着快速的切换,以达到看上去是同时运行的效果。
我们可以形象把多线程的运行形容为在互相抢夺cpu的执行权。

这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长,cpu说的算。
在没有你特意控制的情况下,cpu会刻意的将某个线程一直执行完才去执行另外一个线程,他不会那么做,,,他在快速切换优化资源,,

如果你想看到cpu切换效果,你可以人为控制,,比如shleep,或者wait,,,让某个线程先暂停下,,,

比如:sleep

public class Ticket implements Runnable{
        private  int tick = 10;
       
        public void run()
        {
                while(true)
                {
                       
                                if(tick>0)
                                {
                                        try{Thread.sleep(1000);}catch(Exception e){}      //这里让线程睡觉先
                                        System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
                                }
                       
                }
        }
}

回复 使用道具 举报
你那是双核的电脑配上那个超级牛的i1的cpu处理器,,能跑出来结果就不错了,还总是纠结于这种问题。。。
回复 使用道具 举报
没有规律的,每次执行结果都不一样,两个线程都在这行,谁抢到cup的执行权就执行谁。
回复 使用道具 举报
因为可能CPU是双核的,jvm在线程同步的时候可能会让没一个核执行一个线程一次来实现线程同步,而每个核的当前占有率有所不同,所以造成了输出不是交叉的
回复 使用道具 举报
傅宇 中级黑马 2013-3-10 22:17:54
7#
因为你CPU在两个线程之间快速切换之前,一个线程已经完成了300次输出“我”(或“你”),我帮你代码改了一下,通过sleep()方法让线程阻塞一段时间,就能看出切换的效果了。
  1. class Demo extends Thread
  2. {
  3.         private String name;
  4.         Demo(String name)
  5.         {
  6.          this.name=name;
  7.         }
  8.         public void run()
  9.         {
  10.          for(int x=0;x<20;x++){
  11.                                 System.out.println(name);
  12.                                 try{
  13.                                 Thread.sleep(2000);}
  14.                                 catch(InterruptedException e){
  15.                                 }}
  16.         }
  17. }

  18. public class ThreadDemo
  19. {
  20.         public static void main(String[] args)
  21.         {
  22.          Demo d1=new Demo("我");
  23.          Demo d2=new Demo("你");
  24.          d1.start();
  25.          d2.start();
  26.         }
  27. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
本帖最后由 邹学良 于 2013-3-10 22:11 编辑

因为你没设定线程执行条件,D1和D2是谁拿到资源谁执行,根本没什么规律可而的,当然运气好的话也可能能打印出你要的效果,或者你当上帝,设置优先级
如果想要交替打印的效果的话,简单一点就是加入sleep()语句,让进行执行的线程停一下,
而如果要完全交替执行,可以通过用wait()和notify()机制来作为线程实现,这两个方法的前提是要把也作为D1和D2的共享数据

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。。有可能你的是双核,或者有可能你的cpu主频很高。所以看不出效果。我这个破电脑就可以看出效果了。或者你可以把两个对象的优先级设置成不同,就会看到效果了,或者你可以设置条件 。当x = 某个数是,线程sleep(),这样也可以看到效果。希望能帮到你。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
想要交叉话,要用到线程间的通信,等待唤醒机制,
关于这个知识点在毕老师的视频中,第12天视频中有的,特别是第5 个视频(生产者和消费者).
回复 使用道具 举报
你的电脑是双核的把?这样的 话就不好说是哪个先出或后出了
回复 使用道具 举报
那是因为现在有二个线程在同时执行,cpu在这二个线程间快速的切换,随机性造成了结果的没规律。
  所以你的这个结果是很正常的了
  多运行几次就可以了。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 你试了吗

查看全部评分

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