网易的一道java笔试题,不甚明白是何居心,求大神讲解
package netease;public class VolatileTest { private static int number;
private static boolean ready;
private static class ReadThread extends Thread{
public void run(){
while(!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
new ReadThread().start();
number = 42;
ready = true;
}}1) 上面的代码输出什么,并说明原因?
2)若ready是volatile修饰,输出什么,说明原因?
package netease;public class VolatileTest { private static int number;
private static boolean ready;
private static class ReadThread extends Thread{
public void run(){
while(!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
new ReadThread().start();
number = 42;
ready = true;
}}1) 上面的代码输出什么,并说明原因?
2)若ready是volatile修饰,输出什么,说明原因?
也可能啥都没打印
……http://www.ticmy.com/?p=5http://www.ticmy.com/?p=118
ReaderThread线程的Thread.yield()方法使得main主线程优先使用CPU,不会导致ReadThread().start()后CPU被独占而使main的number = 42;ready = true;等无法执行。因此,ReaderThread线程的while循环有限次后(次数不定)ready = true;停止循环并输出42由于main执行时间太短,楼主代码还看不出Thread.yield()方法“让步”的情况,稍微改了下,可运行看看(每次的结果都不一样)public class test4 {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread
{
public void run()
{
int j=0;
while(!ready)
{
System.out.println("ReaderThread-out-"+j);
Thread.yield();
j++;
}
System.out.println(number);
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
new ReaderThread().start();
number = 42;
for(int i=0;i<1000;i++){
System.out.println("main-out-"+i);
}
ready = true;
}
}
2.加不加volatile修饰符没什么影响,最多是0或者42打的少一点
只是迟早的事情
1、ReadThread看到了number为42,ready为false
2、ReadThread看到了number为0,ready为false
3、ReadThread看到了number为42,ready为true
4、ReadThread看到了number为0,ready为true还要加两种:
1、main线程执行结束了,ReadThread线程还没开始
2、ReadThread线程执行结束了,main线程的赋值还没做
new ReadThread().start();这句话其实可以分成两句
ReadThread th=new ReadThread(); ---1
th.start(); ---2
这样大家就好理解了,执行第一句时,会执行类的初始化。由于ready和number为静态变量,他们会在类初始化时也被初始化,所以相当于这样
private static boolean ready;
private static int number;
public ReadThread(){
number = 42;
ready = true;
} 这样以后再执行th.start();大家可以去网上搜下JAVA中关于类的初始化和类的加载放面的知识
public class VolatileTest { private static int number;
private static boolean ready; private static class ReadThread extends Thread{
public void run(){
System.out.println("while1"+ready);
System.out.println("while2"+number);
while(!ready)
Thread.yield();
System.out.println("让步后1"+ready);
System.out.println("让步后2"+number);
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println(number);
System.out.println(ready);
ReadThread th=new ReadThread();
System.out.println("MAIN"+number);
System.out.println("main"+ready);
th.start();
number = 42;
System.out.println("何时执行");
ready = true;
} }
控制台输出:
0
false
MAIN0
mainfalse
何时执行
while1true
while242
让步后1true
让步后242
如果加volatile, 只能打出42因为volatile 关键字有一个作用是 禁止指令重排序优化,就是java 内存模型中所描述的 Within Thread As If Serial Semantics