1,java虚拟机采用抢占式调度模型,但线程调度又不是跨平台的,如果在能分时间片式的操作系统中,线程调度机制到底是如何呢?
2,重写的run方法中,如果没有调用sleep(),yield(),join()等方法,整个线程类中也没有设置线程优先级,那么线程实例是不是挨个运行的呢?如MyThread t1 =new MyThread();MyThread t2 = new MyThread();分别start()后,是不是t1生命周期结束后才开始运行呢?
3,
public class FirstThread extends Thread{
/**
 * thread1 输出偶数,thread2 输出奇数 ,数目50
 */
public void run(){
for(int i=1;i<=50;i++){
if(currentThread().getName().equals("thread1")&&i%2==0)
System.out.println("thread1:"+i);
else if(currentThread().getName().equals("thread2")&&i%2!=0)
System.out.println("thread2:"+i);
}
}
public static void main(String[] args) {
FirstThread t1 = new FirstThread();
t1.setName("thread1");
FirstThread t2 = new FirstThread();
t2.setName("thread2");
t1.start();
t2.start();
}
}为什么结果是先输出全部偶数再全部输出奇数,体现不出两线程并发。而把i换成大数如500,结果就会奇偶杂乱。

解决方案 »

  1.   

    当i很小的时候,在t2还没有完成启动的时候t1就已经完成所有打印了,所以体现不出并发
    JVM的线程调度会使用操作系统的线程调度;如果没有,则使用多个进程模拟线程调度。
    这个由JVM本身负责处理,使程序可以认为他们是等价的。
      

  2.   

    那如何才能在i很小的时候体现出并发呢?如果不人为让运行中线程让出CPU的话。
      

  3.   

    让thread1 wait() 等待thread2的notify()
      

  4.   

    那就调用yield方法如果不让出CPU时间,t1在一个非常短时间就已经完成了,根本来不及让t2有足够的时间开始运行,所以必须让出CPU时间或者足够长时间才可以出现t1 t2同时在运行的情况
      

  5.   

    谢谢以上各位回答,还是不太明白JVM线程调度机制与操作系统调度机制的关系
      

  6.   

    2,重写的run方法中,如果没有调用sleep(),yield(),join()等方法,整个线程类中也没有设置线程优先级,那么线程实例是不是挨个运行的呢?如MyThread   t1   =new   MyThread();MyThread   t2   =   new   MyThread();分别start()后,是不是t1生命周期结束后才开始运行呢? 如果你有足够的CPU的话,那么t1 start后,t2进行start,t2不会等到t1结束后再start.
      

  7.   

    JVM的线程调度实现多数是利用操作系统本身的实现来完成的,前提是操作系统支持线程及优先级等
    如果操作系统不支持,部分JVM是使用fork多个进程来模拟实现,具体的JVM实现你可以去看看JVM的源代码(好像现在有下载吧,我是没有下载过)不过其实你不必太过于在意它如何实现,毕竟不同JVM有不同结果,关键是你要理解线程的运行规律
      

  8.   

    JVM线程调度依赖操作系统调度机制
    对于我们来说可以看作纯粹是乱序执行的、多线程执行顺序无法准确预测
    我们的程序能控制的只有告诉一个线程什么情况下sleep、wait或notifyall。或指定某个线程yield()和join()。
      

  9.   

    线程是由JVM虚拟机调用的,在没有设定优先级、也没有调用sleep(),yield(),join()等方法的时候哪个线程先运行是不确定的,这个问题是有你的电脑决定的。
    你那个程序当i=50时,偶数那个线程在还JVM还没有调用奇数线程的时候,已经结束了。然而,你把数字改大,使得偶数线程运行的时间延长,JVM就能有时间调用奇数线程。所以就导致你那运行结果。至于你说的是不是你个线程运行完再运行另一个:当线程调用start()方法后就生成了线程对象,线程就进入了Runnable状态,可是还不是Running状态。也就是说在start()方法后只是把线程放入可运行池,而还没有进入运行池,线程怎么运行是由你的CPU决定的。
      

  10.   

    我想就是cpu轮转时间片.
    thread1.start();
    thread2.start();cpu先分配给thread1时间片 然后再给thread2.
      

  11.   

    当i很小的时候,在t2还没机会启动 你可以在t1那sleep一下 就能看出来了 小的时候也可以的
      

  12.   

    t1 start后,程序就接着执行t2里,不会等t1结束的
    http://www.10zhizui.cn