因为刚学习java不久,对于多线程有一点不解,就是如果各个线程的优先级如果一样的话(包括主线程),那么如果主线程和其他线程同时为就绪状态,当然此时有一个线程在运行,当这个线程处于阻塞状态时,究竟是主线程还是其他线程成为运行状态?下面有一段代码,为何主线程不能在当前线程处于阻塞状态时开始运行,而一定要等待两个线程运行结束,主线程睡眠时间无论多少都会等待其他线程运行结束吗,为什么会是这样?如果不想让主线程等待的话该怎样做呢,请各位指点
package occupycpu;
public class Machine extends Thread{
  private static StringBuffer log=new StringBuffer();
  private static int count=0;  public void run(){
    for(int a=0;a<20;a++){
      log.append(currentThread().getName()+":"+a+" ");
      if(++count %10==0)log.append("\n");
      try{
       sleep(100);
      }catch(InterruptedException e){
       throw new RuntimeException(e);
      }
     }
  }
  public static void main(String args[])throws Exception{
    Machine machine1=new Machine();
    Machine machine2=new Machine();
    machine1.setName("m1");
    machine2.setName("m2");
    machine1.start();
    machine2.start();
    while(machine1.isAlive() || machine2.isAlive())
      Thread.sleep(5);  //主线程睡眠5秒,等待machine1和machine2线程运行结束
    System.out.println(log);
  }
}

解决方案 »

  1.   

    machine1和machine2的线程状态并不是受到其它线程的影响的,除了正在sleep时状态为TIMED_WAITING外,for循环中状态为RUNNABLE的,也就是machine1和machine2可以同时处于RUNNABLE的,JVM是为自动为多个RUNNABLE的线程作调度的。上述代码上,如果不想在main中使用while循环可以使用machine1.join();mainchine2.join()这样来直接等待两个线程的结束
      

  2.   

    非常感谢,照ChDw说的那样,我将while(machine1.isAlive()  ¦ ¦ machine2.isAlive())这句话注释掉,加上mainchine2.join();这样程序依旧可以顺利运行结束想再问一个问题,不知道是不是有点偏,就是关于运行结果,因为线程对象的name最后都将追加到一个StringBuffer中,但是既然在同一时间只有一个线程在运行,那么应该是machine1和machine2哪个线程线运行,它在StringBuffer中的name应该始终在另一个线程的前面,但是结果却不是这样,时而m1在前,时而m2在前,请问这是怎么回事?
      

  3.   

    如果只有一个CPU则实际上只有一个线程在执行代码,
    但是你不能肯定JVM是调度哪个线程执行代码,这个是不确定的。在多线程环境中,如果你不使用同步代码(wait、sychronized之类),你不应该猜测代码的执行顺序所以m1, m2的顺序会乱
      

  4.   

    使用sychronized标记的话,它只是为了资源的互斥使用,并不能锁定线程啊!!!
    我想用调用yeild()方法应该行的。——————————————————————继续探讨,我也是初学者
      

  5.   

    主线程在等待machine1线程的结束,那么在machine1线程的结束之前,实际在运行的就是machine1和machine2,两个线程轮流占用cpu,而machine1首先运行,然后sleep,machine2再运行,然后machine2再sleep,把sleep时间调得足够长,应该可以始终保持两个线程的运行先后次序吧,只是结果会出现m1:0 m2:0 m1:1 m2:1 m2:2 m1:2.....会在某一时刻突然先执行machine2,就比如当log追加到m2:1时,此时machine2应该处于sleep状态,machine1处于可运行状态,而且cpu没有被别的线程占用,那么为什么machine1不能执行呢,难道JVM调度线程的时候,并不完全是哪个线程处于就绪状态而且cpu空闲就运行它,而是早已经定好线程的执行次序,即使当前cpu空闲并且有处于就绪状态的线程也不会让其执行还有一个问题,就是因为我加的语句是machine1.join();所以当machine1结束后,应该就会运行主线程,存在一个问题就是在最后的代码执行阶段,machine1执行后,machine2没有执行之前,主线程应该就会运行吧,这是结果中应该不会出现m2:19,但是每次的结果中都会出现m2:19,即使将run()中的sleep()调得足够长,主线程也会等待machine2执行完后再执行,可是明明用的machine1.join();
    修改后的代码如下:
    package occupycpu; 
    public class Machine extends Thread{ 
      private static StringBuffer log=new StringBuffer(); 
      private static int count=0;   public void run(){ 
        for(int a=0;a <20;a++){ 
          log.append(currentThread().getName()+":"+a+" "); 
          if(++count %10==0)log.append("\n"); 
          try{ 
           sleep(200); 
          }catch(InterruptedException e){ 
           throw new RuntimeException(e); 
          } 
         } 
      } 
      public static void main(String args[])throws Exception{ 
        Machine machine1=new Machine(); 
        Machine machine2=new Machine(); 
        machine1.setName("m1"); 
        machine2.setName("m2"); 
        machine1.start(); 
        machine2.start(); 
        machine1.join(); 
        System.out.println(log); 
      } 
    }
      

  6.   

    public class Machine extends Thread{ 
      private static StringBuffer log=new StringBuffer(); 
      private static int count=0;   public void run(){ 
        for(int a=0;a <20;a++){ 
          log.append(currentThread().getName()+":"+a+" "); 
          if(++count %10==0)log.append("\n"); 
          try{ 
           sleep(100); 
          }catch(InterruptedException e){ 
           throw new RuntimeException(e); 
          } 
         } 
      } 
      
         public static void waitForit(Machine machine11,Machine machine22)
        {try
         {machine11.join();
         }catch(InterruptedException e){}
            machine22.start(); 
         }
        
        
      public static void main(String args[])throws Exception{ 
        Machine machine1=new Machine(); 
        Machine machine2=new Machine(); 
        machine1.setName("m1"); 
        machine2.setName("m2"); 
        machine1.start(); 
        machine2.waitForit(machine1,machine2);
           // 1、 while(machine1.isAlive()  || machine2.isAlive())       Thread.sleep(5);  //主线程睡眠5秒,等待machine1和machine2线程运行结束 
        System.out.println(log); 
      } 
    }
    哈哈 我也实现了 不过他的资源被互斥了  
      

  7.   

          Thread.sleep(10000);  //主线程睡眠足够长时间,就可以把所有的数据都输出了  ^_^
      

  8.   

    两个线程轮流占用cpu,而machine1首先运行,然后sleep,machine2再运行,然后machine2再sleep,把sleep时间调得足够长,应该可以始终保持两个线程的运行先后次序吧
    ----
    错误!!线程中的代码执行是需要时间的,也就是append和println需要花费时间的,而且sleep并非一个精确的函数,它只是保证线程最小sleep这么多时间,在到达这个时间时并不意味着线程的代码可以马上得到执行。所以我已经强调了,你不能对多线程中的执行时间作任何的假设!