黑马程序员技术交流社区

标题: 关于多线程的问题 [打印本页]

作者: 沈子豪    时间: 2013-3-10 21:19
标题: 关于多线程的问题
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();
        }
}
这是双线程,但是为什么输出要么先是"我",要么先是"你",为什么不是交叉的?


作者: 文密    时间: 2013-3-10 21:32
那是因为现在有二个线程在同时执行,cpu在这二个线程间快速的切换,随机性造成了结果的没规律。
  所以你的这个结果是很正常的了
  多运行几次就可以了。
作者: 马甲大王    时间: 2013-3-10 21:35
你的电脑是双核的把?这样的 话就不好说是哪个先出或后出了
作者: 叶征东    时间: 2013-3-10 21:44
想要交叉话,要用到线程间的通信,等待唤醒机制,
关于这个知识点在毕老师的视频中,第12天视频中有的,特别是第5 个视频(生产者和消费者).
作者: 张宁    时间: 2013-3-10 21:55
当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。。有可能你的是双核,或者有可能你的cpu主频很高。所以看不出效果。我这个破电脑就可以看出效果了。或者你可以把两个对象的优先级设置成不同,就会看到效果了,或者你可以设置条件 。当x = 某个数是,线程sleep(),这样也可以看到效果。希望能帮到你。
作者: 邹学良    时间: 2013-3-10 22:09
本帖最后由 邹学良 于 2013-3-10 22:11 编辑

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

作者: 张文星    时间: 2013-3-10 22:28
因为可能CPU是双核的,jvm在线程同步的时候可能会让没一个核执行一个线程一次来实现线程同步,而每个核的当前占有率有所不同,所以造成了输出不是交叉的
作者: 黑马17期-闫东东    时间: 2013-3-10 23:53
没有规律的,每次执行结果都不一样,两个线程都在这行,谁抢到cup的执行权就执行谁。
作者: 刘辉    时间: 2013-3-11 00:01
你那是双核的电脑配上那个超级牛的i1的cpu处理器,,能跑出来结果就不错了,还总是纠结于这种问题。。。
作者: 聂斌    时间: 2013-3-11 00:19
本帖最后由 聂斌 于 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--);
                                }
                       
                }
        }
}






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